#include "WmmxImageLib32.h"
#include <stdio.h>
#include <stdlib.h>
#include <math.h>

struct _ErrorColor{
    float dR;
    float dG;
    float dB;
};

inline int Power2m1(int exp)
{
    int result = 1;
    for (int i=0;i<exp;i++) {
        result =result<<1;
    }
    return result-1;
}

inline long getC8Color(const long rColor){
    return rColor*(((1<<16)*255+30)/31) >>16;
}

inline long getBestColor(const float wantColor, int precision){
    float result=float(wantColor*((float(precision))/255));
    if (result<=0)
        return 0;
    else if (result>=precision)
        return precision;
    else
        return (long)result;
}

inline void BlendPixel(PIXEL Src, int x, int y, IMAGE *img, unsigned char srcAlpha)
{
    PIXEL* Dst = (PIXEL*)img->pData;
    ((char*&)Dst)+=img->nPitch*y;
    Dst+=x;

    Dst->A = ((Src.A*srcAlpha)>>8) + ((Dst->A * (255-srcAlpha))>>8) > 255 ? 255 : ((Src.A*srcAlpha)>>8) + ((Dst->A * (255-srcAlpha))>>8);
    Dst->R = ((Src.R*srcAlpha)>>8) + ((Dst->R * (255-srcAlpha))>>8) > 255 ? 255 : ((Src.R*srcAlpha)>>8) + ((Dst->R * (255-srcAlpha))>>8);
    Dst->G = ((Src.G*srcAlpha)>>8) + ((Dst->G * (255-srcAlpha))>>8) > 255 ? 255 : ((Src.G*srcAlpha)>>8) + ((Dst->G * (255-srcAlpha))>>8);
    Dst->B = ((Src.B*srcAlpha)>>8) + ((Dst->B * (255-srcAlpha))>>8) > 255 ? 255 : ((Src.B*srcAlpha)>>8) + ((Dst->B * (255-srcAlpha))>>8);
}


inline void BlendPixel2(IMAGE *srcImg, int x, int y, IMAGE *img, unsigned char srcAlpha)
{
    PIXEL* Dst = (PIXEL*)img->pData;
    PIXEL* Src = (PIXEL*)srcImg->pData;
    ((char*&)Dst)+=img->nPitch*y;
    ((char*&)Src)+=srcImg->nPitch*y;
    Dst+=x;
    Src+=x;

    unsigned char alpha = (Src->A * srcAlpha)>>8;

    Dst->A = ((Src->A*srcAlpha)>>8) + ((Dst->A * (255-alpha))>>8) > 255 ? 255 : ((Src->A*srcAlpha)>>8) + ((Dst->A * (255-alpha))>>8);
    Dst->R = ((Src->R*srcAlpha)>>8) + ((Dst->R * (255-alpha))>>8) > 255 ? 255 : ((Src->R*srcAlpha)>>8) + ((Dst->R * (255-alpha))>>8);
    Dst->G = ((Src->G*srcAlpha)>>8) + ((Dst->G * (255-alpha))>>8) > 255 ? 255 : ((Src->G*srcAlpha)>>8) + ((Dst->G * (255-alpha))>>8);
    Dst->B = ((Src->B*srcAlpha)>>8) + ((Dst->B * (255-alpha))>>8) > 255 ? 255 : ((Src->B*srcAlpha)>>8) + ((Dst->B * (255-alpha))>>8);

}

inline PIXEL PixelAlpha888_PreMul(PIXEL Src, PIXEL Dst, unsigned char srcAlpha)
{
    PIXEL Result;

    unsigned char alpha = (Src.A * srcAlpha)>>8;

    Result.A = ((Src.A*srcAlpha)>>8) + ((Dst.A * (255-alpha))>>8) > 255 ? 255 : ((Src.A*srcAlpha)>>8) + ((Dst.A * (255-alpha))>>8);
    Result.R = ((Src.R*srcAlpha)>>8) + ((Dst.R * (255-alpha))>>8) > 255 ? 255 : ((Src.R*srcAlpha)>>8) + ((Dst.R * (255-alpha))>>8);
    Result.G = ((Src.G*srcAlpha)>>8) + ((Dst.G * (255-alpha))>>8) > 255 ? 255 : ((Src.G*srcAlpha)>>8) + ((Dst.G * (255-alpha))>>8);
    Result.B = ((Src.B*srcAlpha)>>8) + ((Dst.B * (255-alpha))>>8) > 255 ? 255 : ((Src.B*srcAlpha)>>8) + ((Dst.B * (255-alpha))>>8);

    return Result;
//    return ( (unsigned char*)((unsigned char*)pic.paData+pic.naPitch*y) )[x];
}


void GradientFillColor(int* gradientTable, int x0, int y0, int vx, int vy, IMAGE *img)
{
    int x,y;
    unsigned char* imgDst = img->pData;
    int* dst = (int*)imgDst;
    int width = img->nWidth;
    int pitch = img->nPitch;
    //int x_16 = x0<<16;
    int len = vx*vx+vy*vy;

#ifndef _EVC

    int incx_16 = int(((long long int)(vx)<<24)/len);
    int incy_16 = int(((long long int)(vy)<<24)/len);

#else

    int incx_16 = int((_int64(vx)<<24)/len);
    int incy_16 = int((_int64(vy)<<24)/len);

#endif

    int gx_16 = 0;
    int temp;
    int gx0_16 = -incx_16*x0;
    x0 = width-1;

    for(y=y0;y>=0;y--) {
        gx_16 = gx0_16;
        dst=(int*)(imgDst+pitch*y);
        for (x=x0;x>=0;x--) {
            temp = (gx_16>>16);
            if (temp<0) temp=0;
            if (temp>255) temp=255;
            *dst++ = gradientTable[temp];
            gx_16+=incx_16;
        }
        gx0_16 += incy_16;
    }
}

void GradientFillAlpha(unsigned char* gradientTable, int x0, int y0, int vx, int vy, IMAGE *img)
{

}

void ScanLeftAAEdge(POSITION ps, POSITION pe, ScanLineList * scanlinelist, int startY, int height, IMAGE * srcImg, IMAGE * dstImg, int level)
{
	int dx=pe.x-ps.x;
	int dy=pe.y-ps.y;
	int xinc,yinc,i,x,y;

	if (dx>0)
		xinc=1;
	else
		xinc=-1;

	if(dy>0)
		yinc=1;
	else
		yinc=-1;

	dx=abs(dx);
	dy=abs(dy);
	x=pe.x;
	y=pe.y;
	scanlinelist[y-startY].Left.x = x;
	scanlinelist[y-startY].Left.y = y;
    BlendPixel2(srcImg, x, y, dstImg, level);
	x=ps.x;
	y=ps.y;
	scanlinelist[y-startY].Left.x = x;
	scanlinelist[y-startY].Left.y = y;
    BlendPixel2(srcImg, x, y, dstImg, level);

	i=0;

	if(dx==0&&dy==0)
		BlendPixel2(srcImg, x, y, dstImg, level);
	else if(dx==0)
	{
		for(i=0;i<dy;i++)
		{
			BlendPixel2(srcImg, x, y, dstImg, level);
            scanlinelist[y-startY].Left.x = x;
            scanlinelist[y-startY].Left.y = y;
			y+=yinc;
		}
	}
	else if(dy==0)
	{
		for(i=0;i<dx;i++)
		{
			BlendPixel2(srcImg, x, y, dstImg, level);
			x+=xinc;
		}
	}
	else if(dx>dy)
	{
	    if (xinc>0) {
    	    int y_16 = y<<16;
            int dy_16 = (dy<<16)/dx;
            for(i=0;i<dx;i++) {
                BlendPixel2(srcImg, x, (y_16>>16)+1, dstImg, (((y_16&0xFFFF)>>8)*level)>>8);
                scanlinelist[(y_16>>16)+1-startY].Left.x = x+1;
                scanlinelist[(y_16>>16)+1-startY].Left.y = (y_16>>16);
                y_16+=dy_16;
                x+=xinc;
            }
		}
		else {
    	    int y_16 = y<<16;
            int dy_16 = (dy<<16)/dx;
            for(i=0;i<dx;i++) {
                BlendPixel2(srcImg, x,  y_16>>16, dstImg, (((0xFFFF-(y_16&0xFFFF))>>8)*level)>>8);
                scanlinelist[(y_16>>16)+1-startY].Left.x = x;
                scanlinelist[(y_16>>16)+1-startY].Left.y = (y_16>>16)+1;
                y_16+=dy_16;
                x+=xinc;
            }
		}
	}
	else
	{
	    int x_16 = x<<16;
        int dx_16 = (dx<<16)/dy;
        if (xinc<0) {
           dx_16=-dx_16;
        }
		for(i=0;i<dy;i++) {
		    BlendPixel2(srcImg, x_16>>16, y, dstImg, (((0xFFFF-(x_16&0xFFFF))>>8)*level)>>8);
            scanlinelist[y-startY].Left.x = (x_16>>16)+1;
            scanlinelist[y-startY].Left.y = y;
		    x_16+=dx_16;
		    y+=yinc;
		}
	}
	return;
}

void ScanRightAAEdge(POSITION ps, POSITION pe, ScanLineList * scanlinelist, int startY, int height, IMAGE * srcImg, IMAGE * dstImg, int level)
{
	int dx=pe.x-ps.x;
	int dy=pe.y-ps.y;
	int xinc,yinc,i,x,y;

	if (dx>0)
		xinc=1;
	else
		xinc=-1;

	if(dy>0)
		yinc=1;
	else
		yinc=-1;

	dx=abs(dx);
	dy=abs(dy);

	x=pe.x;
	y=pe.y;
	scanlinelist[y-startY].Right.x = x;
	scanlinelist[y-startY].Right.y = y;
//    SetPixel(x, y, color, img);

	x=ps.x;
	y=ps.y;
	scanlinelist[y-startY].Right.x = x;
	scanlinelist[y-startY].Right.y = y;
//    SetPixel(x, y, color, img);

	i=0;

	if(dx==0&&dy==0)
		BlendPixel2(srcImg, x, y, dstImg, level);
	else if(dx==0)
	{
		for(i=0;i<dy;i++)
		{
			BlendPixel2(srcImg, x, y, dstImg, level);
            scanlinelist[y-startY].Right.x = x;
            scanlinelist[y-startY].Right.y = y;
			y+=yinc;
		}
	}

	else if(dy==0)
	{
		for(i=0;i<dx;i++)
		{
			BlendPixel2(srcImg, x, y, dstImg, level);
			x+=xinc;
		}
	}

	else if(dx>dy)
	{
	    if (xinc>0) {
    	    int y_16 = y<<16;
            int dy_16 = (dy<<16)/dx;
            for(i=0;i<dx;i++) {
                BlendPixel2(srcImg, x,  y_16>>16, dstImg, (((0xFFFF-(y_16&0xFFFF))>>8)*level)>>8);
                scanlinelist[(y_16>>16)+1-startY].Right.x = x;
                scanlinelist[(y_16>>16)+1-startY].Right.y = (y_16>>16)+1;
                y_16+=dy_16;
                x+=xinc;
            }
		}
		else {
    	    int y_16 = y<<16;
            int dy_16 = (dy<<16)/dx;
            for(i=0;i<dx;i++) {
                BlendPixel2(srcImg, x+1, (y_16>>16)+1, dstImg, (((y_16&0xFFFF)>>8)*level)>>8);
                scanlinelist[(y_16>>16)+1-startY].Right.x = x;
                scanlinelist[(y_16>>16)+1-startY].Right.y = (y_16>>16);
                y_16+=dy_16;
                x+=xinc;
            }
		}
	}
	else
	{
	    int x_16 = x<<16;
        int dx_16 = (dx<<16)/dy;
        if (xinc<0) {
           dx_16=-dx_16;
        }
		for(i=0;i<dy;i++) {
		    BlendPixel2(srcImg, (x_16>>16)+1, y, dstImg, (((x_16&0xFFFF)>>8)*level)>>8);
            scanlinelist[y-startY].Right.x = (x_16>>16);
            scanlinelist[y-startY].Right.y = y;
		    x_16+=dx_16;
		    y+=yinc;
		}
	}
	return;
}

void FillPolygon(ScanLineList * scanlinelist, int startY, int height, IMAGE * srcImg, IMAGE * dstImg, int level)
{
    int y = 0;
//    if ((srcImg->nImageType&3) == 3) {
//    while (y<height) {
//        int startX = scanlinelist[y].Left.x;
//        int endX = scanlinelist[y].Right.x;
//            int* dst = (int*)dstImg->pData;
//            ((unsigned char*&)dst)+=dstImg->nPitch*(y+startY);
//            dst+=startX;
//            int* src = (int*)srcImg->pData;
//            ((unsigned char*&)src)+=srcImg->nPitch*(y+startY);
//            src+=startX;
//            for (int x=startX;x<=endX;x++) {
//                (*(PIXEL*)dst) = PixelAlpha888_PreMul((*(PIXEL*)src), (*(PIXEL*)dst), level);
//                src++;
//                dst++;
//            }
//            y++;
//        }
//    }
//    else if ((srcImg->nImageType&3) == 2) {
        while (y<height) {
            int startX = scanlinelist[y].Left.x;
            int endX = scanlinelist[y].Right.x;
            int* dst = (int*)dstImg->pData;
            ((unsigned char*&)dst)+=dstImg->nPitch*(y+startY);
            dst+=startX;
            int* src = (int*)srcImg->pData;
            ((unsigned char*&)src)+=srcImg->nPitch*(y+startY);
            src+=startX;
            for (int x=startX;x<=endX;x++) {
                *dst = *src;
                src++;
                dst++;
            }
            y++;
        }
//    }
}

void DrawAAPolygon(POSITION * leftVertexList, int LEdgeNum, POSITION * rightVertexList, int REdgeNum, IMAGE * srcImg, IMAGE * dstImg, int level)
{
    int startY = leftVertexList[0].y;
    int height = leftVertexList[LEdgeNum].y - leftVertexList[0].y;
    ScanLineList * scanlinelist = new ScanLineList[height+2];

    int i;
    for (i=0;i<LEdgeNum;i++) {
        ScanLeftAAEdge(leftVertexList[i], leftVertexList[i+1], scanlinelist, startY, height, srcImg, dstImg, level);
    }
    for (i=0;i<REdgeNum;i++) {
        ScanRightAAEdge(rightVertexList[i], rightVertexList[i+1], scanlinelist, startY, height, srcImg, dstImg, level);
    }

    FillPolygon(scanlinelist, startY, height, srcImg, dstImg, level);

    if (scanlinelist)
        delete [] scanlinelist;
}

void BresenhamDrawLine(int xs,int ys,int xe,int ye, int color, IMAGE * img)
{
	int dx=xe-xs;
	int dy=ye-ys;
	int xinc,yinc,i,x,y;

	if(dx>0)
		xinc=1;
	else
		xinc=-1;

	if(dy>0)
		yinc=1;
	else
		yinc=-1;

	dx=abs(dx);
	dy=abs(dy);
	x=xs;
	y=ys;
	i=0;

	if(dx==0&&dy==0)
		SetPixel(x, y, color, img);
	else if(dx==0)
	{
		for(i=0;i<dy;i++)
		{
			SetPixel(x, y, color, img);
			y+=yinc;
		}
	}
	else if(dy==0)
	{
		for(i=0;i<dx;i++)
		{
			SetPixel(x, y, color, img);
			x+=xinc;
		}
	}
	else if(dx>dy)
	{
		int p=2*dy-dx;
		int inc1=2*dy,inc2=2*(dy-dx);
		for(i=0;i<dx;i++)
		{
			SetPixel(x, y, color, img);
			x+=xinc;
			if(p<0)
				p+=inc1;
			else
			{
				y+=yinc;
				p+=inc2;
			}
		}
	}
	else
	{
		int p=2*dx-dy;
		int inc1=2*dx,inc2=2*(dx-dy);
		for(i=0;i<dy;i++)
		{
			SetPixel(x, y, color, img);
			y+=yinc;
			if(p<0)
				p+=inc1;
			else
			{
				x+=xinc;
				p+=inc2;
			}
		}
	}
	return;
}

void DrawAALine(int xs,int ys,int xe,int ye, int color, IMAGE * img)
{
	int dx=xe-xs;
	int dy=ye-ys;
	int xinc,yinc,i,x,y;
	PIXEL Src;
	Src.A = 0xFF;
	Src.R = (color>>16)&0xFF;
	Src.G = (color>>8)&0xFF;
	Src.B =  color&0xFF;

	if(dx>0)
		xinc=1;
	else
		xinc=-1;

	if(dy>0)
		yinc=1;
	else
		yinc=-1;

	dx=abs(dx);
	dy=abs(dy);
	x=xs;
	y=ys;
	i=0;

	if(dx==0&&dy==0)
		SetPixel(x, y, color, img);
	else if(dx==0)
	{
		for(i=0;i<dy;i++)
		{
			SetPixel(x, y, color, img);
			y+=yinc;
		}
	}
	else if(dy==0)
	{
		for(i=0;i<dx;i++)
		{
			SetPixel(x, y, color, img);
			x+=xinc;
		}
	}
	else if(dx>dy)
	{
	     int y_16 = y<<16;
         int dy_16 = (dy<<16)/dx;
         if (yinc<0) {
            dy_16=-dy_16;
         }
		for(i=0;i<dx;i++) {
		    BlendPixel(Src, x,  y_16>>16, img, (0xFFFF-(y_16&0xFFFF))>>8);
		    BlendPixel(Src, x, (y_16>>16)+1, img, (y_16&0xFFFF)>>8);
		    y_16+=dy_16;
		    x+=xinc;
		}
	}
	else
	{
	    int x_16 = x<<16;
        int dx_16 = (dx<<16)/dy;
        if (xinc<0) {
           dx_16=-dx_16;
        }
		for(i=0;i<dy;i++) {
		    BlendPixel(Src, x_16>>16, y, img, (0xFFFF-(x_16&0xFFFF))>>8);
		    BlendPixel(Src, (x_16>>16)+1, y, img, (x_16&0xFFFF)>>8);
		    x_16+=dx_16;
		    y+=yinc;
		}
	}
	return;
}

inline unsigned char& Alpha(const IMGREGION& pic,const int x,const int y)
{
    return ( (unsigned char*)((unsigned char*)pic.paData+pic.naPitch*y) )[x];
}

inline PIXEL Add(PIXEL Src, PIXEL Dst)
{
    PIXEL result;
//    result.A = (Src.A + Dst.A)>255 ? 255 : (Src.A + Dst.A);
    result.G = (Src.G + Dst.G)>255 ? 255 : (Src.G + Dst.G);
    result.B = (Src.B + Dst.B)>255 ? 255 : (Src.B + Dst.B);
    result.R = (Src.R + Dst.R)>255 ? 255 : (Src.R + Dst.R);
    return result;
}

inline short& Pixels(const IMGREGION& pic,const int x,const int y)
{
    return ( (short*)((unsigned char*)pic.pData+pic.nPitch*y) )[x];
}

inline short BilInear1(const IMGREGION& pic,const int x_16,const int y_16)
{
    unsigned int x=x_16>>16;
    unsigned int y=y_16>>16;
    short Color0=Pixels(pic,x,y);
    short Color2=Pixels(pic,x+1,y);
    short Color1=Pixels(pic,x,y+1);
    short Color3=Pixels(pic,x+1,y+1);

    unsigned int u_8=(x_16 & 0xFFFF)>>8;
    unsigned int v_8=(y_16 & 0xFFFF)>>8;
    unsigned int pm3_16=(u_8*v_8);
    unsigned int pm2_16=(u_8*(unsigned int)(255-v_8));
    unsigned int pm1_16=(v_8*(unsigned int)(255-u_8));
    unsigned int pm0_16=((255-u_8)*(255-v_8));

    short result = 0;

    result |=((pm0_16*(Color0&31)+pm1_16*(Color1&31)+pm2_16*(Color2&31)+pm3_16*(Color3&31))>>16);
    result |=((pm0_16*(Color0>>5&63)+pm1_16*(Color1>>5&63)+pm2_16*(Color2>>5&63)+pm3_16*(Color3>>5&63))>>16)<<5;
    result |=((pm0_16*(Color0>>11&31)+pm1_16*(Color1>>11&31)+pm2_16*(Color2>>11&31)+pm3_16*(Color3>>11&31))>>16)<<11;

    return result;
}


inline unsigned char BilInearAlpha(const IMGREGION& pic,const int x_16,const int y_16)
{
    unsigned int x=x_16>>16;
    unsigned int y=y_16>>16;
    unsigned char Color0=Alpha(pic,x,y);
    unsigned char Color2=Alpha(pic,x+1,y);
    unsigned char Color1=Alpha(pic,x,y+1);
    unsigned char Color3=Alpha(pic,x+1,y+1);

    unsigned int u_8=(x_16 & 0xFFFF)>>8;
    unsigned int v_8=(y_16 & 0xFFFF)>>8;
    unsigned int pm3_16=(u_8*v_8);
    unsigned int pm2_16=(u_8*(unsigned int)(255-v_8));
    unsigned int pm1_16=(v_8*(unsigned int)(255-u_8));
    unsigned int pm0_16=((255-u_8)*(255-v_8));

    unsigned char result = 0;

    result = ((pm0_16*(Color0)+pm1_16*(Color1)+pm2_16*(Color2)+pm3_16*(Color3))>>16);

    return result;
}

inline short AlphaBlend(short wpSrc, short wpDes, unsigned char wAlpha)
{

        short wb = wpSrc;
        short wa = wpDes;
        unsigned char alpha = wAlpha;
        short result =0;

        result |=(alpha*((wb&31)-(wa&31))>>8)+(wa&31);
        result |=((alpha*((wb>>5&63)-(wa>>5&63))>>8)+(wa>>5&63))<<5;
        result |=((alpha*((wb>>11&31)-(wa>>11&31))>>8)+(wa>>11&31))<<11;

        return result;

}

inline unsigned char AlphaBlend8(unsigned char src, unsigned char dst, unsigned char alpha)
{
    return ((alpha * (src - dst))>>8) + dst;
}

inline PIXEL Alpha888(PIXEL Src, PIXEL Dst, unsigned char alpha)
{
    PIXEL Result;
    Result.R = ((alpha * (Src.R - Dst.R))>>8) + Dst.R;
    Result.G = ((alpha * (Src.G - Dst.G))>>8) + Dst.G;
    Result.B = ((alpha * (Src.B - Dst.B))>>8) + Dst.B;
    return Result;
//    return ( (unsigned char*)((unsigned char*)pic.paData+pic.naPitch*y) )[x];
}

inline PIXEL Alpha888_PreMul(PIXEL Src, PIXEL Dst, unsigned char alpha)
{
    PIXEL Result;

    if (0xFF == Src.A) {
        return Src;
    }
    else if (0 == Src.A) {
        return Dst;
    }
    else {
        Result.A = ((Src.A*alpha)>>8)+((Dst.A*(255-alpha))>>8) > 255 ? 255 : ((Src.A*alpha)>>8)+((Dst.A*(255-alpha))>>8);
        Result.R = ((Src.R*alpha)>>8)+((Dst.R*(255-alpha))>>8) > 255 ? 255 : ((Src.R*alpha)>>8)+((Dst.R*(255-alpha))>>8);
        Result.G = ((Src.G*alpha)>>8)+((Dst.G*(255-alpha))>>8) > 255 ? 255 : ((Src.G*alpha)>>8)+((Dst.G*(255-alpha))>>8);
        Result.B = ((Src.B*alpha)>>8)+((Dst.B*(255-alpha))>>8) > 255 ? 255 : ((Src.B*alpha)>>8)+((Dst.B*(255-alpha))>>8);
    }

    return Result;
//    return ( (unsigned char*)((unsigned char*)pic.paData+pic.naPitch*y) )[x];
}

inline PIXEL PixelAlpha888(PIXEL Src, PIXEL Dst, unsigned char alpha)
{
    PIXEL Result;

    alpha = (Src.A * alpha)>>8;

    Result.R = ((alpha * (Src.R - Dst.R))>>8) + Dst.R;
    Result.G = ((alpha * (Src.G - Dst.G))>>8) + Dst.G;
    Result.B = ((alpha * (Src.B - Dst.B))>>8) + Dst.B;
    return Result;
//    return ( (unsigned char*)((unsigned char*)pic.paData+pic.naPitch*y) )[x];
}


void Blit565WMMX(const ALPHABLITSTRUCT & AlphaBlitStruct)
{
    int height = AlphaBlitStruct.iDstH;
    int width = AlphaBlitStruct.iDstW;

    short * Src = (short *)AlphaBlitStruct.lpSrc;
    short * Dst = (short *)AlphaBlitStruct.lpDst;

    for (int y = 0; y < height; y++) {
        for (int x = 0; x < width; x++) {
            Dst[x] = Src [x];
        }
        ((char*&)Src)+=AlphaBlitStruct.iSrcPitch;
        ((char*&)Dst)+=AlphaBlitStruct.iDstPitch;
    }
}

void AlphaBlit565(const ALPHABLITSTRUCT & AlphaBlitStruct)
{
    int height = AlphaBlitStruct.iDstH;
    int width = AlphaBlitStruct.iDstW;

    short * Src = (short *)AlphaBlitStruct.lpSrc;
    short * Dst = (short *)AlphaBlitStruct.lpDst;
    unsigned char * Alp =          AlphaBlitStruct.lpAlpha;

    for (int y = 0; y < height; y++) {
        for (int x = 0; x < width; x++) {
            Dst[x] = AlphaBlend(Src[x], Dst[x], Alp[x]);
        }
        ((char*&)Src)+=AlphaBlitStruct.iSrcPitch;
        ((char*&)Alp)+=AlphaBlitStruct.iAlpPitch;
        ((char*&)Dst)+=AlphaBlitStruct.iDstPitch;
    }

}

void AlphaBlend565(const ALPHABLITSTRUCT & AlphaBlitStruct)
{
    int height = AlphaBlitStruct.iDstH;
    int width = AlphaBlitStruct.iDstW;

    short * Src = (short *)AlphaBlitStruct.lpSrc;
    short * Dst = (short *)AlphaBlitStruct.lpDst;
    unsigned char    Level = AlphaBlitStruct.AlphaValue;

    for (int y = 0; y < height; y++) {
        for (int x = 0; x < width; x++) {
            Dst[x] = AlphaBlend(Src[x], Dst[x], Level);
        }
        ((char*&)Src)+=AlphaBlitStruct.iSrcPitch;
        ((char*&)Dst)+=AlphaBlitStruct.iDstPitch;
    }

}

//
//void ParticleBlitBlend565(const ALPHABLITSTRUCT & AlphaBlitStruct)
//{
//    int height = AlphaBlitStruct.iDstH;
//    int width = AlphaBlitStruct.iDstW;
//
//
//    short SrcColor = (short)AlphaBlitStruct.lpSrc;
//    short * Dst = (short *)AlphaBlitStruct.lpDst;
//    unsigned char  * Alp =          AlphaBlitStruct.lpAlpha;
//    unsigned char    Level = AlphaBlitStruct.AlphaValue;
//    int    TempAlpha = 0;
//
//    for (int y = 0; y < height; y++) {
//        for (int x = 0; x < width; x++) {
//            TempAlpha = (Alp[x] * Level)>>8;
//            Dst[x] = AlphaBlend(SrcColor, Dst[x], (unsigned char)TempAlpha);
//        }
//        ((char*&)Alp)+=AlphaBlitStruct.iAlpPitch;
//        ((char*&)Dst)+=AlphaBlitStruct.iDstPitch;
//    }
//}

void AlphaBlitBlend565(const ALPHABLITSTRUCT & AlphaBlitStruct)
{
    int height = AlphaBlitStruct.iDstH;
    int width = AlphaBlitStruct.iDstW;

    short * Src = (short *)AlphaBlitStruct.lpSrc;
    short * Dst = (short *)AlphaBlitStruct.lpDst;
    unsigned char  * Alp =          AlphaBlitStruct.lpAlpha;
    unsigned char    Level = AlphaBlitStruct.AlphaValue;
    int    TempAlpha = 0;

    for (int y = 0; y < height; y++) {
        for (int x = 0; x < width; x++) {
            TempAlpha = (Alp[x] * Level)>>8;
            Dst[x] = AlphaBlend(Src[x], Dst[x], (unsigned char)TempAlpha);
        }
        ((char*&)Src)+=AlphaBlitStruct.iSrcPitch;
        ((char*&)Alp)+=AlphaBlitStruct.iAlpPitch;
        ((char*&)Dst)+=AlphaBlitStruct.iDstPitch;
    }
}

void MemcpyC(unsigned char * Src, unsigned char * Dst, int Size)
{
    for (int i=0;i<Size;i++) {
        Dst[i] = Src[i];
    }
//		memcpy(Dst,Src,Size);
}

inline short BilInear(short* PColor0,short* PColor1,unsigned long u_8,unsigned long v_8)
{
    unsigned long pm3_16=u_8*v_8;
    unsigned long pm2_16=(u_8<<8)-pm3_16;
    unsigned long pm1_16=(v_8<<8)-pm3_16;
    unsigned long pm0_16=(65535)-pm1_16-pm2_16-pm3_16;

    short result;
    //DebugBreak();
    result  =(unsigned short)(((pm0_16*(PColor0[0]&31)+pm2_16*(PColor0[1]&31)+pm1_16*(PColor1[0]&31)+pm3_16*(PColor1[1]&31))>>16));
    result |=(unsigned short)(((pm0_16*(PColor0[0]>>5&63)+pm2_16*(PColor0[1]>>5&63)+pm1_16*(PColor1[0]>>5&63)+pm3_16*(PColor1[1]>>5&63))>>16)<<5);
    result |=(unsigned short)(((pm0_16*(PColor0[0]>>11&31)+pm2_16*(PColor0[1]>>11&31)+pm1_16*(PColor1[0]>>11&31)+pm3_16*(PColor1[1]>>11&31))>>16)<<11);
    //result.b=((pm0_16*PColor0[0].b+pm2_16*PColor0[1].b+pm1_16*PColor1[0].b+pm3_16*PColor1[1].b)>>16);

    return result;
}


inline unsigned char BilIneara(unsigned char* PColor0, unsigned char* PColor1,unsigned long u_8,unsigned long v_8)
{
    unsigned long pm3_16=u_8*v_8;
    unsigned long pm2_16=(u_8<<8)-pm3_16;
    unsigned long pm1_16=(v_8<<8)-pm3_16;
    unsigned long pm0_16=(65535)-pm1_16-pm2_16-pm3_16;

    unsigned char result;
    //DebugBreak();
    result  =(unsigned char)((pm0_16*PColor0[0]+pm2_16*PColor0[1]+pm1_16*PColor1[0]+pm3_16*PColor1[1])>>16);
//    result |=((pm0_16*(PColor0[0]>>5&63)+pm2_16*(PColor0[1]>>5&63)+pm1_16*(PColor1[0]>>5&63)+pm3_16*(PColor1[1]>>5&63))>>16)<<5;
//    result |=((pm0_16*(PColor0[0]>>11&31)+pm2_16*(PColor0[1]>>11&31)+pm1_16*(PColor1[0]>>11&31)+pm3_16*(PColor1[1]>>11&31))>>16)<<11;
    //result.b=((pm0_16*PColor0[0].b+pm2_16*PColor0[1].b+pm1_16*PColor1[0].b+pm3_16*PColor1[1].b)>>16);

    return result;
}


void ZoomBilInearWMMXCalc(const IMGREGION& Src,const IMGREGION& Dst, unsigned long xrIntFloat_16, unsigned long yrIntFloat_16)
{
    int dst_width=Dst.nWidth;
    long Src_byte_width=Src.nPitch;
    short* pDstLine=Dst.pData;
    unsigned long srcy_16=0;

    for (int y=0;y<Dst.nHeight;++y) {
        unsigned long v_8=(srcy_16 & 0xFFFF)>>8;
        short* PSrcLineColor= (short*)((unsigned char*)(Src.pData)+Src_byte_width*(srcy_16>>16));
        //short* PSrcLineColorNext= (short*)((unsigned char*)(PSrcLineColor)+Src_byte_width;

        unsigned long srcx_16=0;
        for (int x=0;x<dst_width;++x)
        {
            short* PColor0=&PSrcLineColor[srcx_16>>16];
            pDstLine[x]=BilInear(PColor0,(short*)((unsigned char*)(PColor0)+Src_byte_width),(srcx_16 & 0xFFFF)>>8,v_8);
            //pDstLine[x]=Pixels(Src,x,y);
            srcx_16+=xrIntFloat_16;
        }

        srcy_16+=yrIntFloat_16;
        ((unsigned char*&)pDstLine)+=Dst.nPitch;
    }
}

void ZoomBilInearWMMXaCalc(const IMGREGION& Src,const IMGREGION& Dst,unsigned long xrIntFloat_16,unsigned long yrIntFloat_16)
{
    int dst_width=Dst.nWidth;
    long Src_byte_width=Src.nPitch;
    long Src_Alpha_width=Src.naPitch;
    short* pDstLine=Dst.pData;
    unsigned char* pDstLinea=Dst.paData;
    unsigned long srcy_16=0;

    for (int y=0;y<Dst.nHeight;++y)
    {
        unsigned long v_8=(srcy_16 & 0xFFFF)>>8;
        short* PSrcLineColor= (short*)((unsigned char*)(Src.pData)+Src_byte_width*(srcy_16>>16));
        unsigned char* PSrcLineColora= (unsigned char*)((unsigned char*)(Src.paData)+Src_Alpha_width*(srcy_16>>16));
        //short* PSrcLineColorNext= (short*)((unsigned char*)(PSrcLineColor)+Src_byte_width;

        unsigned long srcx_16=0;
        for (int x=0;x<dst_width;++x)
        {

            short* PColor0=&PSrcLineColor[srcx_16>>16];
            unsigned char* PColora0=&PSrcLineColora[srcx_16>>16];
            pDstLine[x]=BilInear(PColor0,(short*)((unsigned char*)(PColor0)+Src_byte_width),(srcx_16 & 0xFFFF)>>8,v_8);
            pDstLinea[x]= BilIneara(PColora0,((unsigned char*)(PColora0)+Src_Alpha_width),(srcx_16 & 0xFFFF)>>8,v_8);
            //pDstLine[x]=Pixels(Src,x,y);
            srcx_16+=xrIntFloat_16;
        }

        srcy_16+=yrIntFloat_16;
        ((unsigned char*&)pDstLine)+=Dst.nPitch;
        ((unsigned char*&)pDstLinea)+=Dst.naPitch;
    }
}

void ZoomBilInearWMMXbCalc(const IMGREGION& Src,const IMGREGION& Dst,unsigned long xrIntFloat_16,unsigned long yrIntFloat_16)
{
    //DebugBreak();
    int dst_width=Dst.nWidth;
    long Src_Alpha_width=Src.naPitch;
    unsigned char* pDstLinea=Dst.paData;
    unsigned long srcy_16=0;

    for (int y=0;y<Dst.nHeight;++y)
    {
        unsigned long v_8=(srcy_16 & 0xFFFF)>>8;
        unsigned char* PSrcLineColora= (unsigned char*)((unsigned char*)(Src.paData)+Src_Alpha_width*(srcy_16>>16));
        //short* PSrcLineColorNext= (short*)((unsigned char*)(PSrcLineColor)+Src_byte_width;

        unsigned long srcx_16=0;
        for (int x=0;x<dst_width;++x)
        {
            unsigned char* PColora0=&PSrcLineColora[srcx_16>>16];
            pDstLinea[x]=BilIneara(PColora0,((unsigned char*)(PColora0)+Src_Alpha_width),(srcx_16 & 0xFFFF)>>8,v_8);
            //pDstLine[x]=Pixels(Src,x,y);
            srcx_16+=xrIntFloat_16;
        }

        srcy_16+=yrIntFloat_16;
        ((unsigned char*&)pDstLinea)+=Dst.naPitch;
    }
}

void EraseBackgroundWMMX(short * dst, unsigned short color, int count)
{
    count = count>>1;
    for (int i=0;i < count;i++) {
        dst[i] = color;
    }
}

//void RGB888To565_P4(IMAGE * image, SURFACE * surface)
//{
//    int i, width, height;
//    unsigned char *R, *G, *B;
//    short temp;
//    short * dst;
//
//    R = image->R;
//    G = image->G;
//    B = image->B;
//    dst = surface->pData;
//    width = image->nWidth;
//    height = image->nHeight;
//
//    for (i=0; i<width*height; i++) {
//        temp = B[i]>>3;
//        temp |= (G[i]>>2)<<5;
//        temp |= (R[i]>>3)<<11;
//        dst[i] = temp;
//    }
//}

void RGB888To565(IMAGE * image, SURFACE * surface)
{
    int i, width, height;
    PIXEL* src;
    short temp;
    short * dst;

    src = (PIXEL*)image->pData;
    dst = surface->pData;
    width = image->nWidth;
    height = image->nHeight;

    for (i=0; i<width*height; i++) {
        temp = src[i].B>>3;
        temp |= (src[i].G>>2)<<5;
        temp |= (src[i].R>>3)<<11;
        dst[i] = temp;
    }
}

//void AlphaBlit888(_RENDERSTRUCT & renderstruct)
//{
//    PIXEL* pSrc = (PIXEL*)renderstruct.pSrc;
//    PIXEL* pDst = (PIXEL*)renderstruct.pDst;
//
//    int nSrcPitch = renderstruct.nSrcPitch;
//    int nDstPitch = renderstruct.nDstPitch;
//    int height = renderstruct.nHeight;
//    int width = renderstruct.nWidth;
//
//    for (int y = 0; y < height; y++) {
//        for (int x = 0; x < width; x++) {
//            pDst[x].R = AlphaBlend8(pSrc[x].R, pDst[x].R, pSrc[x].A);
//            pDst[x].G = AlphaBlend8(pSrc[x].G, pDst[x].G, pSrc[x].A);
//            pDst[x].B = AlphaBlend8(pSrc[x].B, pDst[x].B, pSrc[x].A);
//        }
//        ((char*&)pSrc)+=nSrcPitch;
//        ((char*&)pDst)+=nDstPitch;
//    }
//}

void AlphaBlit_8u_C4A_PreMul(_RENDERSTRUCT & renderstruct)
{
    PIXEL* pSrc = (PIXEL*)renderstruct.pSrc;
    PIXEL* pDst = (PIXEL*)renderstruct.pDst;

    int nSrcPitch = renderstruct.nSrcPitch;
    int nDstPitch = renderstruct.nDstPitch;
    int height = renderstruct.nHeight;
    int width = renderstruct.nWidth;

    for (int y = 0; y < height; y++) {
        for (int x = 0; x < width; x++) {
            pDst[x] = PixelAlpha888_PreMul(pSrc[x], pDst[x], 255);
        }
        ((char*&)pSrc)+=nSrcPitch;
        ((char*&)pDst)+=nDstPitch;
    }
}

//
//void AlphaBlit888_P4(_RENDERSTRUCT & renderstruct)
//{
//    unsigned char *pAlpha = renderstruct.pAlpha;
//    unsigned char *pSR = renderstruct.pSR;
//    unsigned char *pSG = renderstruct.pSG;
//    unsigned char *pSB = renderstruct.pSB;
//    unsigned char *pDR = renderstruct.pDR;
//    unsigned char *pDG = renderstruct.pDG;
//    unsigned char *pDB = renderstruct.pDB;
//    int nSrcPitch = renderstruct.nSrcPitch;
//    int nDstPitch = renderstruct.nDstPitch;
//    int height = renderstruct.nHeight;
//    int width = renderstruct.nWidth;
//
//    for (int y = 0; y < height; y++) {
//        for (int x = 0; x < width; x++) {
//            pDR[x] = AlphaBlend8(pSR[x], pDR[x], pAlpha[x]);
//            pDG[x] = AlphaBlend8(pSG[x], pDG[x], pAlpha[x]);
//            pDB[x] = AlphaBlend8(pSB[x], pDB[x], pAlpha[x]);
//        }
//        ((char*&)pSR)+=nSrcPitch;
//        ((char*&)pSG)+=nSrcPitch;
//        ((char*&)pSB)+=nSrcPitch;
//        ((char*&)pDR)+=nDstPitch;
//        ((char*&)pDG)+=nDstPitch;
//        ((char*&)pDB)+=nDstPitch;
//        ((char*&)pAlpha)+=nSrcPitch;
//    }
//}


void AlphaBlitBlend_8u_C4A_PreMul(_RENDERSTRUCT & renderstruct)
{
    PIXEL* pSrc = (PIXEL*)renderstruct.pSrc;
    PIXEL* pDst = (PIXEL*)renderstruct.pDst;

    int nSrcPitch = renderstruct.nSrcPitch;
    int nDstPitch = renderstruct.nDstPitch;
    int height = renderstruct.nHeight;
    int width = renderstruct.nWidth;

    int alpha = renderstruct.uAlphaValue;
//    int tempalp = 0;

    for (int y = 0; y < height; y++) {
        for (int x = 0; x < width; x++) {
            pDst[x] = PixelAlpha888_PreMul(pSrc[x], pDst[x], alpha);
        }
        ((char*&)pSrc)+=nSrcPitch;
        ((char*&)pDst)+=nDstPitch;
    }
}

//
//void AlphaBlitBlend888(_RENDERSTRUCT & renderstruct)
//{
//    PIXEL* pSrc = (PIXEL*)renderstruct.pSrc;
//    PIXEL* pDst = (PIXEL*)renderstruct.pDst;
//
//    int nSrcPitch = renderstruct.nSrcPitch;
//    int nDstPitch = renderstruct.nDstPitch;
//    int height = renderstruct.nHeight;
//    int width = renderstruct.nWidth;
//
//    int alpha = renderstruct.uAlphaValue;
//    int tempalp = 0;
//
//    for (int y = 0; y < height; y++) {
//        for (int x = 0; x < width; x++) {
//            tempalp = (pSrc[x].A * alpha)>>8;
//            pDst[x].R = AlphaBlend8(pSrc[x].R, pDst[x].R, tempalp);
//            pDst[x].G = AlphaBlend8(pSrc[x].G, pDst[x].G, tempalp);
//            pDst[x].B = AlphaBlend8(pSrc[x].B, pDst[x].B, tempalp);
//        }
//        ((char*&)pSrc)+=nSrcPitch;
//        ((char*&)pDst)+=nDstPitch;
//    }
//}


void BlendColor_8u_C4A(_RENDERSTRUCT & renderstruct)
{
    PIXEL* pDst = (PIXEL*)renderstruct.pDst;

    int nDstPitch = renderstruct.nDstPitch;
    int height = renderstruct.nHeight;
    int width = renderstruct.nWidth;
    int alpha = renderstruct.uAlphaValue;

    PIXEL Src;
    Src.A = 0xFF;
    Src.B = (unsigned char)(renderstruct.uRenderType>>8);
    Src.G = (unsigned char)(renderstruct.uRenderType>>16);
    Src.R = (unsigned char)(renderstruct.uRenderType>>24);

    for (int y = 0; y < height; y++) {
        for (int x = 0; x < width; x++) {
            pDst[x] = PixelAlpha888_PreMul(Src, pDst[x], alpha);
        }
        ((char*&)pDst)+=nDstPitch;
    }
}


//
//void BlendColor888(_RENDERSTRUCT & renderstruct)
//{
//    PIXEL* pDst = (PIXEL*)renderstruct.pDst;
//
//    int nDstPitch = renderstruct.nDstPitch;
//    int height = renderstruct.nHeight;
//    int width = renderstruct.nWidth;
//    int alpha = renderstruct.uAlphaValue;
//    unsigned char B = (unsigned char)(renderstruct.uRenderType>>8);
//    unsigned char G = (unsigned char)(renderstruct.uRenderType>>16);
//    unsigned char R = (unsigned char)(renderstruct.uRenderType>>24);
//
//    for (int y = 0; y < height; y++) {
//        for (int x = 0; x < width; x++) {
//            pDst[x].R = AlphaBlend8(R, pDst[x].R, alpha);
//            pDst[x].G = AlphaBlend8(G, pDst[x].G, alpha);
//            pDst[x].B = AlphaBlend8(B, pDst[x].B, alpha);
//        }
//        ((char*&)pDst)+=nDstPitch;
//    }
//}

void BlitBlend_8u_C4A_PreMul(_RENDERSTRUCT & renderstruct)
{
    PIXEL* pSrc = (PIXEL*)renderstruct.pSrc;
    PIXEL* pDst = (PIXEL*)renderstruct.pDst;

    int nSrcPitch = renderstruct.nSrcPitch;
    int nDstPitch = renderstruct.nDstPitch;
    int height = renderstruct.nHeight;
    int width = renderstruct.nWidth;
    int alpha = renderstruct.uAlphaValue;

    for (int y = 0; y < height; y++) {
        for (int x = 0; x < width; x++) {
            pDst[x] = Alpha888_PreMul(pSrc[x], pDst[x], alpha);
        }
        ((char*&)pSrc)+=nSrcPitch;
        ((char*&)pDst)+=nDstPitch;
    }
}
//
//void AlphaBlend888(_RENDERSTRUCT & renderstruct)
//{
//    PIXEL* pSrc = (PIXEL*)renderstruct.pSrc;
//    PIXEL* pDst = (PIXEL*)renderstruct.pDst;
//
//    int nSrcPitch = renderstruct.nSrcPitch;
//    int nDstPitch = renderstruct.nDstPitch;
//    int height = renderstruct.nHeight;
//    int width = renderstruct.nWidth;
//    int alpha = renderstruct.uAlphaValue;
//
//    for (int y = 0; y < height; y++) {
//        for (int x = 0; x < width; x++) {
//            pDst[x].R = AlphaBlend8(pSrc[x].R, pDst[x].R, alpha);
//            pDst[x].G = AlphaBlend8(pSrc[x].G, pDst[x].G, alpha);
//            pDst[x].B = AlphaBlend8(pSrc[x].B, pDst[x].B, alpha);
//        }
//        ((char*&)pSrc)+=nSrcPitch;
//        ((char*&)pDst)+=nDstPitch;
//    }
//}
//
//void AlphaBlend888_P4(_RENDERSTRUCT & renderstruct)
//{
//    unsigned char *pSR = renderstruct.pSR;
//    unsigned char *pSG = renderstruct.pSG;
//    unsigned char *pSB = renderstruct.pSB;
//    unsigned char *pDR = renderstruct.pDR;
//    unsigned char *pDG = renderstruct.pDG;
//    unsigned char *pDB = renderstruct.pDB;
//    int nSrcPitch = renderstruct.nSrcPitch;
//    int nDstPitch = renderstruct.nDstPitch;
//    int height = renderstruct.nHeight;
//    int width = renderstruct.nWidth;
//    int alpha = renderstruct.uAlphaValue;
//
//    for (int y = 0; y < height; y++) {
//        for (int x = 0; x < width; x++) {
//            pDR[x] = AlphaBlend8(pSR[x], pDR[x], alpha);
//            pDG[x] = AlphaBlend8(pSG[x], pDG[x], alpha);
//            pDB[x] = AlphaBlend8(pSB[x], pDB[x], alpha);
//        }
//        ((char*&)pSR)+=nSrcPitch;
//        ((char*&)pSG)+=nSrcPitch;
//        ((char*&)pSB)+=nSrcPitch;
//        ((char*&)pDR)+=nDstPitch;
//        ((char*&)pDG)+=nDstPitch;
//        ((char*&)pDB)+=nDstPitch;
//    }
//}

void AlphaOnly_8u_C4A(_RENDERSTRUCT & renderstruct)
{
    unsigned char* pSrc = (unsigned char*)renderstruct.pSrc;
    PIXEL* pDst = (PIXEL*)renderstruct.pDst;
    PIXEL Src;
    Src.R = (unsigned char)(renderstruct.uRenderType>>24);
    Src.G = (unsigned char)(renderstruct.uRenderType>>16);
    Src.B = (unsigned char)(renderstruct.uRenderType>>8);

    int nSrcPitch = renderstruct.nSrcPitch;
    int nDstPitch = renderstruct.nDstPitch;
    int height = renderstruct.nHeight;
    int width = renderstruct.nWidth;


    for (int y = 0; y < height; y++) {
        for (int x = 0; x < width; x++) {
            Src.A = pSrc[x];
            pDst[x] = PixelAlpha888_PreMul(Src, pDst[x], 255);
        }
        ((char*&)pSrc)+=nSrcPitch;
        ((char*&)pDst)+=nDstPitch;
    }
}
//
//void AlphaOnly888(_RENDERSTRUCT & renderstruct)
//{
//    unsigned char* pSrc = (unsigned char*)renderstruct.pSrc;
//    PIXEL* pDst = (PIXEL*)renderstruct.pDst;
//    unsigned char R = (unsigned char)(renderstruct.uRenderType>>24);
//    unsigned char G = (unsigned char)(renderstruct.uRenderType>>16);
//    unsigned char B = (unsigned char)(renderstruct.uRenderType>>8);
//
//    int nSrcPitch = renderstruct.nSrcPitch;
//    int nDstPitch = renderstruct.nDstPitch;
//    int height = renderstruct.nHeight;
//    int width = renderstruct.nWidth;
//
//
//    for (int y = 0; y < height; y++) {
//        for (int x = 0; x < width; x++) {
//            pDst[x].R = AlphaBlend8(R, pDst[x].R, pSrc[x]);
//            pDst[x].G = AlphaBlend8(G, pDst[x].G, pSrc[x]);
//            pDst[x].B = AlphaBlend8(B, pDst[x].B, pSrc[x]);
//        }
//        ((char*&)pSrc)+=nSrcPitch;
//        ((char*&)pDst)+=nDstPitch;
//    }
//}

void AlphaOnlyBlend_8u_C4A(_RENDERSTRUCT & renderstruct)
{
    unsigned char* pSrc = (unsigned char*)renderstruct.pSrc;
    PIXEL* pDst = (PIXEL*)renderstruct.pDst;
    PIXEL Src;
    Src.R = (unsigned char)(renderstruct.uRenderType>>24);
    Src.G = (unsigned char)(renderstruct.uRenderType>>16);
    Src.B = (unsigned char)(renderstruct.uRenderType>>8);

    int nSrcPitch = renderstruct.nSrcPitch;
    int nDstPitch = renderstruct.nDstPitch;
    int height = renderstruct.nHeight;
    int width = renderstruct.nWidth;
    int alpha = renderstruct.uAlphaValue;

    for (int y = 0; y < height; y++) {
        for (int x = 0; x < width; x++) {
            Src.A = pSrc[x];
            pDst[x] = PixelAlpha888_PreMul(Src, pDst[x], alpha);
        }
        ((char*&)pSrc)+=nSrcPitch;
        ((char*&)pDst)+=nDstPitch;
    }
}
//
//void AlphaOnlyBlend888(_RENDERSTRUCT & renderstruct)
//{
//    unsigned char* pSrc = (unsigned char*)renderstruct.pSrc;
//    PIXEL* pDst = (PIXEL*)renderstruct.pDst;
//    unsigned char R = (unsigned char)(renderstruct.uRenderType>>24);
//    unsigned char G = (unsigned char)(renderstruct.uRenderType>>16);
//    unsigned char B = (unsigned char)(renderstruct.uRenderType>>8);
//
//    int nSrcPitch = renderstruct.nSrcPitch;
//    int nDstPitch = renderstruct.nDstPitch;
//    int height = renderstruct.nHeight;
//    int width = renderstruct.nWidth;
//    int alpha = renderstruct.uAlphaValue;
//    int tempalp = 0;
//
//    for (int y = 0; y < height; y++) {
//        for (int x = 0; x < width; x++) {
//            tempalp = (pSrc[x] * alpha)>>8;
//            pDst[x].R = AlphaBlend8(R, pDst[x].R, tempalp);
//            pDst[x].G = AlphaBlend8(G, pDst[x].G, tempalp);
//            pDst[x].B = AlphaBlend8(B, pDst[x].B, tempalp);
//        }
//        ((char*&)pSrc)+=nSrcPitch;
//        ((char*&)pDst)+=nDstPitch;
//    }
//}

//
//void AlphaOnlyBlend888_P4(_RENDERSTRUCT & renderstruct)
//{
//    unsigned char *pAlpha = renderstruct.pAlpha;
//    unsigned char R = (unsigned char)renderstruct.pSR;
//    unsigned char G = (unsigned char)renderstruct.pSG;
//    unsigned char B = (unsigned char)renderstruct.pSB;
//    unsigned char *pDR = renderstruct.pDR;
//    unsigned char *pDG = renderstruct.pDG;
//    unsigned char *pDB = renderstruct.pDB;
//    int nSrcPitch = renderstruct.nSrcPitch;
//    int nDstPitch = renderstruct.nDstPitch;
//    int height = renderstruct.nHeight;
//    int width = renderstruct.nWidth;
//    int alpha = renderstruct.uAlphaValue;
//    int tempalp = 0;
//
//    for (int y = 0; y < height; y++) {
//        for (int x = 0; x < width; x++) {
//            tempalp = (pAlpha[x] * alpha)>>8;
//            pDR[x] = AlphaBlend8(R, pDR[x], tempalp);
//            pDG[x] = AlphaBlend8(G, pDG[x], tempalp);
//            pDB[x] = AlphaBlend8(B, pDB[x], tempalp);
//        }
//        ((char*&)pDR)+=nDstPitch;
//        ((char*&)pDG)+=nDstPitch;
//        ((char*&)pDB)+=nDstPitch;
//        ((char*&)pAlpha)+=nSrcPitch;
//    }
//}



void Blit888(_RENDERSTRUCT & renderstruct)
{
    PIXEL* pSrc = (PIXEL*)renderstruct.pSrc;
    PIXEL* pDst = (PIXEL*)renderstruct.pDst;

    int nSrcPitch = renderstruct.nSrcPitch;
    int nDstPitch = renderstruct.nDstPitch;
    int height = renderstruct.nHeight;
    int width = renderstruct.nWidth;

    for (int y = 0; y < height; y++) {
        for (int x = 0; x < width; x++) {
            pDst[x].R = pSrc[x].R;
            pDst[x].G = pSrc[x].G;
            pDst[x].B = pSrc[x].B;
        }
        ((char*&)pSrc)+=nSrcPitch;
        ((char*&)pDst)+=nDstPitch;
    }
}


void Add888(_RENDERSTRUCT & renderstruct)
{
    PIXEL* pSrc = (PIXEL*)renderstruct.pSrc;
    PIXEL* pDst = (PIXEL*)renderstruct.pDst;

    int nSrcPitch = renderstruct.nSrcPitch;
    int nDstPitch = renderstruct.nDstPitch;
    int height = renderstruct.nHeight;
    int width = renderstruct.nWidth;

    for (int y = 0; y < height; y++) {
        for (int x = 0; x < width; x++) {
            pDst[x].A = (pSrc[x].A + pDst[x].A) < 255 ? (pSrc[x].A + pDst[x].A) : 255;
            pDst[x].R = (pSrc[x].R + pDst[x].R) < 255 ? (pSrc[x].R + pDst[x].R) : 255;
            pDst[x].G = (pSrc[x].G + pDst[x].G) < 255 ? (pSrc[x].G + pDst[x].G) : 255;
            pDst[x].B = (pSrc[x].B + pDst[x].B) < 255 ? (pSrc[x].B + pDst[x].B) : 255;
        }
        ((char*&)pSrc)+=nSrcPitch;
        ((char*&)pDst)+=nDstPitch;
    }
}


//
//void Blit888_P4(_RENDERSTRUCT & renderstruct)
//{
//    unsigned char *pSR = renderstruct.pSR;
//    unsigned char *pSG = renderstruct.pSG;
//    unsigned char *pSB = renderstruct.pSB;
//    unsigned char *pDR = renderstruct.pDR;
//    unsigned char *pDG = renderstruct.pDG;
//    unsigned char *pDB = renderstruct.pDB;
//    int nSrcPitch = renderstruct.nSrcPitch;
//    int nDstPitch = renderstruct.nDstPitch;
//    int height = renderstruct.nHeight;
//    int width = renderstruct.nWidth;
//
//    for (int y = 0; y < height; y++) {
//        for (int x = 0; x < width; x++) {
//            pDR[x] = pSR[x];
//            pDG[x] = pSG[x];
//            pDB[x] = pSB[x];
//        }
//        ((char*&)pSR)+=nSrcPitch;
//        ((char*&)pSG)+=nSrcPitch;
//        ((char*&)pSB)+=nSrcPitch;
//        ((char*&)pDR)+=nDstPitch;
//        ((char*&)pDG)+=nDstPitch;
//        ((char*&)pDB)+=nDstPitch;
//    }
//}

void SetColor888(_RENDERSTRUCT & renderstruct)
{
    PIXEL* pDst = (PIXEL*)renderstruct.pDst;

    unsigned char B = (unsigned char)(renderstruct.uRenderType);
    unsigned char G = (unsigned char)(renderstruct.uRenderType>>8);
    unsigned char R = (unsigned char)(renderstruct.uRenderType>>16);
    unsigned char A = (unsigned char)(renderstruct.uRenderType>>24);

    int nDstPitch = renderstruct.nDstPitch;
    int height = renderstruct.nHeight;
    int width = renderstruct.nWidth;

    for (int y = 0; y < height; y++) {
        for (int x = 0; x < width; x++) {
            pDst[x].A = A;
            pDst[x].R = R;
            pDst[x].G = G;
            pDst[x].B = B;
        }
        ((char*&)pDst)+=nDstPitch;
    }
}

//
//void SetColor888_P4(IMAGE & image, unsigned int color)
//{
//    unsigned char *pR = image.R;
//    unsigned char *pG = image.G;
//    unsigned char *pB = image.B;
//    unsigned char B = (unsigned char)color;
//    unsigned char G = (unsigned char)(color>>8);
//    unsigned char R = (unsigned char)(color>>16);
//
//    int width = image.nWidth;
//    int height = image.nHeight;
//
//    for (int y = 0; y < height; y++) {
//        for (int x = 0; x < width; x++) {
//            pR[x] = R;
//            pG[x] = G;
//            pB[x] = B;
//        }
//        ((char*&)pR)+=width;
//        ((char*&)pG)+=width;
//        ((char*&)pB)+=width;
//    }
//}

//
//void ResizeBilinear_8u_P4(IMAGE& Src, IMAGE& Dst,unsigned long xrIntFloat_16,unsigned long yrIntFloat_16)
//{
//    unsigned char* pSrcA = Src.A;
//    unsigned char* pSrcR = Src.R;
//    unsigned char* pSrcG = Src.G;
//    unsigned char* pSrcB = Src.B;
//
//    unsigned char* pDstA = Dst.A;
//    unsigned char* pDstR = Dst.R;
//    unsigned char* pDstG = Dst.G;
//    unsigned char* pDstB = Dst.B;
//
//    int dst_width=Dst.nWidth;
//    int Src_Pitch=Src.nPitch;
//
//    unsigned long srcy_16=0;
//
//    for (int y=0;y<Dst.nHeight;++y)
//    {
//        unsigned long v_8=(srcy_16 & 0xFFFF)>>8;
//        unsigned char* PSrcLineColorr= (unsigned char*)((unsigned char*)(pSrcR)+Src_Pitch*(srcy_16>>16));
//        unsigned char* PSrcLineColorg= (unsigned char*)((unsigned char*)(pSrcG)+Src_Pitch*(srcy_16>>16));
//        unsigned char* PSrcLineColorb= (unsigned char*)((unsigned char*)(pSrcB)+Src_Pitch*(srcy_16>>16));
//        unsigned char* PSrcLineColora= (unsigned char*)((unsigned char*)(pSrcA)+Src_Pitch*(srcy_16>>16));
//
//        unsigned long srcx_16=0;
//        for (int x=0;x<dst_width;++x)
//        {
//            unsigned char* PColorr0=&PSrcLineColorr[srcx_16>>16];
//            unsigned char* PColorg0=&PSrcLineColorg[srcx_16>>16];
//            unsigned char* PColorb0=&PSrcLineColorb[srcx_16>>16];
//            unsigned char* PColora0=&PSrcLineColora[srcx_16>>16];
//            pDstR[x]=BilIneara(PColorr0,((unsigned char*)(PColorr0)+Src_Pitch),(srcx_16 & 0xFFFF)>>8,v_8);
//            pDstG[x]=BilIneara(PColorg0,((unsigned char*)(PColorg0)+Src_Pitch),(srcx_16 & 0xFFFF)>>8,v_8);
//            pDstB[x]=BilIneara(PColorb0,((unsigned char*)(PColorb0)+Src_Pitch),(srcx_16 & 0xFFFF)>>8,v_8);
//            pDstA[x]=BilIneara(PColora0,((unsigned char*)(PColora0)+Src_Pitch),(srcx_16 & 0xFFFF)>>8,v_8);
//            srcx_16+=xrIntFloat_16;
//        }
//
//        srcy_16+=yrIntFloat_16;
//        ((unsigned char*&)pDstR)+=Dst.nPitch;
//        ((unsigned char*&)pDstG)+=Dst.nPitch;
//        ((unsigned char*&)pDstB)+=Dst.nPitch;
//        ((unsigned char*&)pDstA)+=Dst.nPitch;
//    }
//}
//
//
//void ResizeBilinear_8u_P3(IMAGE& Src, IMAGE& Dst,unsigned long xrIntFloat_16,unsigned long yrIntFloat_16)
//{
//    unsigned char* pSrcR = Src.R;
//    unsigned char* pSrcG = Src.G;
//    unsigned char* pSrcB = Src.B;
//
//    unsigned char* pDstR = Dst.R;
//    unsigned char* pDstG = Dst.G;
//    unsigned char* pDstB = Dst.B;
//
//    int dst_width=Dst.nWidth;
//    int Src_Pitch=Src.nPitch;
//
//    unsigned long srcy_16=0;
//
//    for (int y=0;y<Dst.nHeight;++y)
//    {
//        unsigned long v_8=(srcy_16 & 0xFFFF)>>8;
//        unsigned char* PSrcLineColorr= (unsigned char*)((unsigned char*)(pSrcR)+Src_Pitch*(srcy_16>>16));
//        unsigned char* PSrcLineColorg= (unsigned char*)((unsigned char*)(pSrcG)+Src_Pitch*(srcy_16>>16));
//        unsigned char* PSrcLineColorb= (unsigned char*)((unsigned char*)(pSrcB)+Src_Pitch*(srcy_16>>16));
//
//        unsigned long srcx_16=0;
//        for (int x=0;x<dst_width;++x)
//        {
//            unsigned char* PColorr0=&PSrcLineColorr[srcx_16>>16];
//            unsigned char* PColorg0=&PSrcLineColorg[srcx_16>>16];
//            unsigned char* PColorb0=&PSrcLineColorb[srcx_16>>16];
//            pDstR[x]=BilIneara(PColorr0,((unsigned char*)(PColorr0)+Src_Pitch),(srcx_16 & 0xFFFF)>>8,v_8);
//            pDstG[x]=BilIneara(PColorg0,((unsigned char*)(PColorg0)+Src_Pitch),(srcx_16 & 0xFFFF)>>8,v_8);
//            pDstB[x]=BilIneara(PColorb0,((unsigned char*)(PColorb0)+Src_Pitch),(srcx_16 & 0xFFFF)>>8,v_8);
//            srcx_16+=xrIntFloat_16;
//        }
//
//        srcy_16+=yrIntFloat_16;
//        ((unsigned char*&)pDstR)+=Dst.nPitch;
//        ((unsigned char*&)pDstG)+=Dst.nPitch;
//        ((unsigned char*&)pDstB)+=Dst.nPitch;
//    }
//}


void ResizeBilinear_8u_P1(IMAGE& Src, IMAGE& Dst,unsigned long xrIntFloat_16,unsigned long yrIntFloat_16)
{
    unsigned char* pSrcA = Src.pData;
    unsigned char* pDstA = Dst.pData;

    int dst_width=Dst.nWidth;
    int Src_Pitch=Src.nPitch;

    unsigned long srcy_16=0;

    for (int y=0;y<Dst.nHeight;++y)
    {
        unsigned long v_8=(srcy_16 & 0xFFFF)>>8;
        unsigned char* PSrcLineColora= (unsigned char*)((unsigned char*)(pSrcA)+Src_Pitch*(srcy_16>>16));

        unsigned long srcx_16=0;
        for (int x=0;x<dst_width;++x)
        {
            unsigned char* PColora0=&PSrcLineColora[srcx_16>>16];
            pDstA[x]=BilIneara(PColora0,((unsigned char*)(PColora0)+Src_Pitch),(srcx_16 & 0xFFFF)>>8,v_8);
            srcx_16+=xrIntFloat_16;
        }

        srcy_16+=yrIntFloat_16;
        ((unsigned char*&)pDstA)+=Dst.nPitch;
    }
}


inline PIXEL BilInearC4A(PIXEL* PColor0, PIXEL* PColor1,unsigned long u_8,unsigned long v_8)
{
    unsigned long pm3_16=u_8*v_8;
    unsigned long pm2_16=(u_8<<8)-pm3_16;
    unsigned long pm1_16=(v_8<<8)-pm3_16;
    unsigned long pm0_16=(65535)-pm1_16-pm2_16-pm3_16;

    PIXEL result;
    //DebugBreak();
    result.A =(unsigned char)((pm0_16*PColor0[0].A+pm2_16*PColor0[1].A+pm1_16*PColor1[0].A+pm3_16*PColor1[1].A)>>16);
    result.R =(unsigned char)((pm0_16*PColor0[0].R+pm2_16*PColor0[1].R+pm1_16*PColor1[0].R+pm3_16*PColor1[1].R)>>16);
    result.G =(unsigned char)((pm0_16*PColor0[0].G+pm2_16*PColor0[1].G+pm1_16*PColor1[0].G+pm3_16*PColor1[1].G)>>16);
    result.B =(unsigned char)((pm0_16*PColor0[0].B+pm2_16*PColor0[1].B+pm1_16*PColor1[0].B+pm3_16*PColor1[1].B)>>16);

    return result;
}

inline PIXEL BilInearC4(PIXEL* PColor0, PIXEL* PColor1,unsigned long u_8,unsigned long v_8)
{
    unsigned long pm3_16=u_8*v_8;
    unsigned long pm2_16=(u_8<<8)-pm3_16;
    unsigned long pm1_16=(v_8<<8)-pm3_16;
    unsigned long pm0_16=(65535)-pm1_16-pm2_16-pm3_16;

    PIXEL result;
    //DebugBreak();
    result.A = 255;
    result.R = (unsigned char)((pm0_16*PColor0[0].R+pm2_16*PColor0[1].R+pm1_16*PColor1[0].R+pm3_16*PColor1[1].R)>>16);
    result.G = (unsigned char)((pm0_16*PColor0[0].G+pm2_16*PColor0[1].G+pm1_16*PColor1[0].G+pm3_16*PColor1[1].G)>>16);
    result.B = (unsigned char)((pm0_16*PColor0[0].B+pm2_16*PColor0[1].B+pm1_16*PColor1[0].B+pm3_16*PColor1[1].B)>>16);

    return result;
}


void StretchAlphaBlit888_PreMul(_RENDERSTRUCTEX & renderstruct)
{
    unsigned int xrIntFloat_16 = renderstruct.IntFloatX;
    unsigned int yrIntFloat_16 = renderstruct.IntFloatY;
    unsigned int sample = renderstruct.RenderStyle & 1;

    PIXEL* pSrc = (PIXEL*)renderstruct.pSrc;
    PIXEL* pDst = (PIXEL*)renderstruct.pDst;

    int dst_width = renderstruct.nStretchWidth;
    int Src_Pitch = renderstruct.nSrcPitch;

    unsigned long srcy_16=0;

    if (sample) {
        for (int y=0;y<renderstruct.nStretchHeight;++y) {
            unsigned long v_8=(srcy_16 & 0xFFFF)>>8;
            PIXEL* PSrcLineColor= (PIXEL*)((unsigned char*)(pSrc)+Src_Pitch*(srcy_16>>16));

            unsigned long srcx_16=0;
            for (int x=0;x<dst_width;++x)
            {
                PIXEL* PColor0=&PSrcLineColor[srcx_16>>16];
                pDst[x]=PixelAlpha888_PreMul(BilInearC4A(PColor0,(PIXEL*)((unsigned char*)PColor0+Src_Pitch),(srcx_16 & 0xFFFF)>>8,v_8),
                                 pDst[x],255);
                srcx_16+=xrIntFloat_16;
            }

            srcy_16+=yrIntFloat_16;
            ((unsigned char*&)pDst)+=renderstruct.nDstPitch;
        }
    }
    else {
       for (int y=0;y<renderstruct.nStretchHeight;++y) {
//            unsigned long v_8=(srcy_16 & 0xFFFF)>>8;
            PIXEL* PSrcLineColor= (PIXEL*)((unsigned char*)(pSrc)+Src_Pitch*(srcy_16>>16));

            unsigned long srcx_16=0;
            for (int x=0;x<dst_width;++x)
            {
                PIXEL* PColor0=&PSrcLineColor[srcx_16>>16];
                pDst[x]=PixelAlpha888_PreMul(*PColor0,pDst[x],255);
                srcx_16+=xrIntFloat_16;
            }
            srcy_16+=yrIntFloat_16;
            ((unsigned char*&)pDst)+=renderstruct.nDstPitch;
        }
    }
}

//
//void StretchAlphaBlit888(_RENDERSTRUCTEX & renderstruct)
//{
//    unsigned int xrIntFloat_16 = renderstruct.IntFloatX;
//    unsigned int yrIntFloat_16 = renderstruct.IntFloatY;
//    PIXEL* pSrc = (PIXEL*)renderstruct.pSrc;
//    PIXEL* pDst = (PIXEL*)renderstruct.pDst;
//
//    int dst_width = renderstruct.nStretchWidth;
//    int Src_Pitch = renderstruct.nSrcPitch;
//
//    unsigned long srcy_16=0;
//
//    for (int y=0;y<renderstruct.nStretchHeight;++y)
//    {
//        unsigned long v_8=(srcy_16 & 0xFFFF)>>8;
//        PIXEL* PSrcLineColor= (PIXEL*)((unsigned char*)(pSrc)+Src_Pitch*(srcy_16>>16));
//
//        unsigned long srcx_16=0;
//        for (int x=0;x<dst_width;++x)
//        {
//            PIXEL* PColor0=&PSrcLineColor[srcx_16>>16];
//            pDst[x]=PixelAlpha888(BilInearC4A(PColor0,(PIXEL*)((unsigned char*)PColor0+Src_Pitch),(srcx_16 & 0xFFFF)>>8,v_8),
//                             pDst[x],255);
//            srcx_16+=xrIntFloat_16;
//        }
//
//        srcy_16+=yrIntFloat_16;
//        ((unsigned char*&)pDst)+=renderstruct.nDstPitch;
//    }
//}


void StretchAlphaBlitBlend888_PreMul(_RENDERSTRUCTEX & renderstruct)
{
    unsigned int xrIntFloat_16 = renderstruct.IntFloatX;
    unsigned int yrIntFloat_16 = renderstruct.IntFloatY;
    unsigned int sample = renderstruct.RenderStyle & 1;
    PIXEL* pSrc = (PIXEL*)renderstruct.pSrc;
    PIXEL* pDst = (PIXEL*)renderstruct.pDst;

    int dst_width = renderstruct.nStretchWidth;
    int Src_Pitch = renderstruct.nSrcPitch;

    int alpha = renderstruct.uAlphaValue;

    unsigned long srcy_16=0;
    if (sample) {
        for (int y=0;y<renderstruct.nStretchHeight;++y) {
            unsigned long v_8=(srcy_16 & 0xFFFF)>>8;
            PIXEL* PSrcLineColor= (PIXEL*)((unsigned char*)(pSrc)+Src_Pitch*(srcy_16>>16));

            unsigned long srcx_16=0;
            for (int x=0;x<dst_width;++x)
            {
                PIXEL* PColor0=&PSrcLineColor[srcx_16>>16];
                pDst[x]=PixelAlpha888_PreMul(BilInearC4A(PColor0,(PIXEL*)((unsigned char*)PColor0+Src_Pitch),(srcx_16 & 0xFFFF)>>8,v_8),
                                 pDst[x],alpha);
                srcx_16+=xrIntFloat_16;
            }

            srcy_16+=yrIntFloat_16;
            ((unsigned char*&)pDst)+=renderstruct.nDstPitch;
        }
    }
    else {
        for (int y=0;y<renderstruct.nStretchHeight;++y) {
//            unsigned long v_8=(srcy_16 & 0xFFFF)>>8;
            PIXEL* PSrcLineColor= (PIXEL*)((unsigned char*)(pSrc)+Src_Pitch*(srcy_16>>16));

            unsigned long srcx_16=0;
            for (int x=0;x<dst_width;++x)
            {
                PIXEL* PColor0=&PSrcLineColor[srcx_16>>16];
                pDst[x]=PixelAlpha888_PreMul(*PColor0,pDst[x],alpha);
                srcx_16+=xrIntFloat_16;
            }

            srcy_16+=yrIntFloat_16;
            ((unsigned char*&)pDst)+=renderstruct.nDstPitch;
        }
    }
}

//
//void StretchAlphaBlitBlend888(_RENDERSTRUCTEX & renderstruct)
//{
//    unsigned int xrIntFloat_16 = renderstruct.IntFloatX;
//    unsigned int yrIntFloat_16 = renderstruct.IntFloatY;
//    PIXEL* pSrc = (PIXEL*)renderstruct.pSrc;
//    PIXEL* pDst = (PIXEL*)renderstruct.pDst;
//
//    int dst_width = renderstruct.nStretchWidth;
//    int Src_Pitch = renderstruct.nSrcPitch;
//
//    int alpha = renderstruct.uAlphaValue;
//
//    unsigned long srcy_16=0;
//
//    for (int y=0;y<renderstruct.nStretchHeight;++y)
//    {
//        unsigned long v_8=(srcy_16 & 0xFFFF)>>8;
//        PIXEL* PSrcLineColor= (PIXEL*)((unsigned char*)(pSrc)+Src_Pitch*(srcy_16>>16));
//
//        unsigned long srcx_16=0;
//        for (int x=0;x<dst_width;++x)
//        {
//            PIXEL* PColor0=&PSrcLineColor[srcx_16>>16];
//            pDst[x]=PixelAlpha888(BilInearC4A(PColor0,(PIXEL*)((unsigned char*)PColor0+Src_Pitch),(srcx_16 & 0xFFFF)>>8,v_8),
//                             pDst[x],alpha);
//            srcx_16+=xrIntFloat_16;
//        }
//
//        srcy_16+=yrIntFloat_16;
//        ((unsigned char*&)pDst)+=renderstruct.nDstPitch;
//    }
//}


//void StretchAlphaOnlyBlend888_PreMul(_RENDERSTRUCTEX & renderstruct)
//{
//    unsigned int xrIntFloat_16 = renderstruct.IntFloatX;
//    unsigned int yrIntFloat_16 = renderstruct.IntFloatY;
//    unsigned char* pSrc = renderstruct.pSrc;
//    PIXEL* pDst = (PIXEL*)renderstruct.pDst;
//
//    int dst_width = renderstruct.nStretchWidth;
//    int Src_Pitch = renderstruct.nSrcPitch;
//
//    int alpha = renderstruct.uAlphaValue;
//    PIXEL color;
//    color.B = (renderstruct.uRenderType>>8)  & 0xFF;
//    color.G = (renderstruct.uRenderType>>16) & 0xFF;
//    color.R = (renderstruct.uRenderType>>24) & 0xFF;
//
//
//    unsigned long srcy_16=0;
//
//    for (int y=0;y<renderstruct.nStretchHeight;++y)
//    {
//        unsigned long v_8=(srcy_16 & 0xFFFF)>>8;
//        unsigned char* PSrcLineColora= (unsigned char*)((unsigned char*)(pSrc)+Src_Pitch*(srcy_16>>16));
//
//        unsigned long srcx_16=0;
//        for (int x=0;x<dst_width;++x)
//        {
//            unsigned char* PColora0=&PSrcLineColora[srcx_16>>16];
//            color.A = BilIneara(PColora0,((unsigned char*)(PColora0)+Src_Pitch),(srcx_16 & 0xFFFF)>>8,v_8);
//            pDst[x] = PixelAlpha888_PreMul(color, pDst[x], alpha);
//            srcx_16+=xrIntFloat_16;
//        }
//
//        srcy_16+=yrIntFloat_16;
//        ((unsigned char*&)pDst)+=renderstruct.nDstPitch;
//    }
//
//}


void StretchAlphaOnlyBlend888(_RENDERSTRUCTEX & renderstruct)
{
    unsigned int xrIntFloat_16 = renderstruct.IntFloatX;
    unsigned int yrIntFloat_16 = renderstruct.IntFloatY;
    unsigned char* pSrc = renderstruct.pSrc;
    PIXEL* pDst = (PIXEL*)renderstruct.pDst;

    int dst_width = renderstruct.nStretchWidth;
    int Src_Pitch = renderstruct.nSrcPitch;

    int alpha = renderstruct.uAlphaValue;
    PIXEL color;
    color.B = (renderstruct.uRenderType>>8)  & 0xFF;
    color.G = (renderstruct.uRenderType>>16) & 0xFF;
    color.R = (renderstruct.uRenderType>>24) & 0xFF;


    unsigned long srcy_16=0;

    for (int y=0;y<renderstruct.nStretchHeight;++y)
    {
        unsigned long v_8=(srcy_16 & 0xFFFF)>>8;
        unsigned char* PSrcLineColora= (unsigned char*)((unsigned char*)(pSrc)+Src_Pitch*(srcy_16>>16));

        unsigned long srcx_16=0;
        for (int x=0;x<dst_width;++x)
        {
            unsigned char* PColora0=&PSrcLineColora[srcx_16>>16];
            color.A = BilIneara(PColora0,((unsigned char*)(PColora0)+Src_Pitch),(srcx_16 & 0xFFFF)>>8,v_8);
            pDst[x] = PixelAlpha888_PreMul(color, pDst[x], alpha);
            srcx_16+=xrIntFloat_16;
        }

        srcy_16+=yrIntFloat_16;
        ((unsigned char*&)pDst)+=renderstruct.nDstPitch;
    }

}


void StretchBlitBlend888_PreMul(_RENDERSTRUCTEX & renderstruct)
{
    unsigned int xrIntFloat_16 = renderstruct.IntFloatX;
    unsigned int yrIntFloat_16 = renderstruct.IntFloatY;
    unsigned int sample = renderstruct.RenderStyle & 1;
    PIXEL* pSrc = (PIXEL*)renderstruct.pSrc;
    PIXEL* pDst = (PIXEL*)renderstruct.pDst;

    int dst_width = renderstruct.nStretchWidth;
    int Src_Pitch = renderstruct.nSrcPitch;

    int alpha = renderstruct.uAlphaValue;

    unsigned long srcy_16=0;
    if (sample) {
        for (int y=0;y<renderstruct.nStretchHeight;++y) {
            unsigned long v_8=(srcy_16 & 0xFFFF)>>8;
            PIXEL* PSrcLineColor= (PIXEL*)((unsigned char*)(pSrc)+Src_Pitch*(srcy_16>>16));

            unsigned long srcx_16=0;
            for (int x=0;x<dst_width;++x)
            {
                PIXEL* PColor0=&PSrcLineColor[srcx_16>>16];
                pDst[x]=Alpha888_PreMul(BilInearC4A(PColor0,(PIXEL*)((unsigned char*)PColor0+Src_Pitch),(srcx_16 & 0xFFFF)>>8,v_8),
                                 pDst[x],alpha);
                srcx_16+=xrIntFloat_16;
            }

            srcy_16+=yrIntFloat_16;
            ((unsigned char*&)pDst)+=renderstruct.nDstPitch;
        }
    }
    else {
        for (int y=0;y<renderstruct.nStretchHeight;++y) {
//            unsigned long v_8=(srcy_16 & 0xFFFF)>>8;
            PIXEL* PSrcLineColor= (PIXEL*)((unsigned char*)(pSrc)+Src_Pitch*(srcy_16>>16));

            unsigned long srcx_16=0;
            for (int x=0;x<dst_width;++x)
            {
                PIXEL* PColor0=&PSrcLineColor[srcx_16>>16];
                pDst[x]=Alpha888_PreMul(*PColor0,pDst[x],alpha);
                srcx_16+=xrIntFloat_16;
            }

            srcy_16+=yrIntFloat_16;
            ((unsigned char*&)pDst)+=renderstruct.nDstPitch;
        }
    }
}

//
//void StretchBlitBlend888(_RENDERSTRUCTEX & renderstruct)
//{
//    unsigned int xrIntFloat_16 = renderstruct.IntFloatX;
//    unsigned int yrIntFloat_16 = renderstruct.IntFloatY;
//    PIXEL* pSrc = (PIXEL*)renderstruct.pSrc;
//    PIXEL* pDst = (PIXEL*)renderstruct.pDst;
//
//    int dst_width = renderstruct.nStretchWidth;
//    int Src_Pitch = renderstruct.nSrcPitch;
//
//    int alpha = renderstruct.uAlphaValue;
//
//    unsigned long srcy_16=0;
//
//    for (int y=0;y<renderstruct.nStretchHeight;++y)
//    {
//        unsigned long v_8=(srcy_16 & 0xFFFF)>>8;
//        PIXEL* PSrcLineColor= (PIXEL*)((unsigned char*)(pSrc)+Src_Pitch*(srcy_16>>16));
//
//        unsigned long srcx_16=0;
//        for (int x=0;x<dst_width;++x)
//        {
//            PIXEL* PColor0=&PSrcLineColor[srcx_16>>16];
//            pDst[x]=Alpha888(BilInearC4A(PColor0,(PIXEL*)((unsigned char*)PColor0+Src_Pitch),(srcx_16 & 0xFFFF)>>8,v_8),
//                             pDst[x],alpha);
//            srcx_16+=xrIntFloat_16;
//        }
//
//        srcy_16+=yrIntFloat_16;
//        ((unsigned char*&)pDst)+=renderstruct.nDstPitch;
//    }
//}

void StretchBlit888(_RENDERSTRUCTEX & renderstruct)
{
    unsigned int xrIntFloat_16 = renderstruct.IntFloatX;
    unsigned int yrIntFloat_16 = renderstruct.IntFloatY;
    unsigned int sample = renderstruct.RenderStyle & 1;
    PIXEL* pSrc = (PIXEL*)renderstruct.pSrc;
    PIXEL* pDst = (PIXEL*)renderstruct.pDst;

    int dst_width = renderstruct.nStretchWidth;
    int Src_Pitch = renderstruct.nSrcPitch;

    unsigned long srcy_16=0;
    if (sample) {
        for (int y=0;y<renderstruct.nStretchHeight;++y) {
            unsigned long v_8=(srcy_16 & 0xFFFF)>>8;
            PIXEL* PSrcLineColor= (PIXEL*)((unsigned char*)(pSrc)+Src_Pitch*(srcy_16>>16));

            unsigned long srcx_16=0;
            for (int x=0;x<dst_width;++x)
            {
                PIXEL* PColor0=&PSrcLineColor[srcx_16>>16];
                pDst[x]=BilInearC4(PColor0,(PIXEL*)((unsigned char*)PColor0+Src_Pitch),(srcx_16 & 0xFFFF)>>8,v_8);
                srcx_16+=xrIntFloat_16;
            }

            srcy_16+=yrIntFloat_16;
            ((unsigned char*&)pDst)+=renderstruct.nDstPitch;
        }
    }
    else {
        for (int y=0;y<renderstruct.nStretchHeight;++y) {
//            unsigned long v_8=(srcy_16 & 0xFFFF)>>8;
            PIXEL* PSrcLineColor= (PIXEL*)((unsigned char*)(pSrc)+Src_Pitch*(srcy_16>>16));

            unsigned long srcx_16=0;
            for (int x=0;x<dst_width;++x)
            {
                PIXEL* PColor0=&PSrcLineColor[srcx_16>>16];
                pDst[x]=*PColor0;
                srcx_16+=xrIntFloat_16;
            }

            srcy_16+=yrIntFloat_16;
            ((unsigned char*&)pDst)+=renderstruct.nDstPitch;
        }
    }
}


void ResizeBilinear_8u_C4A(IMAGE& Src, IMAGE& Dst,unsigned long xrIntFloat_16,unsigned long yrIntFloat_16)
{
    PIXEL* pSrc = (PIXEL*)Src.pData;
    PIXEL* pDst = (PIXEL*)Dst.pData;

    int dst_width = Dst.nWidth;
    int Src_Pitch = Src.nPitch;

    unsigned long srcy_16=0;

    for (int y=0;y<Dst.nHeight;++y)
    {
        unsigned long v_8=(srcy_16 & 0xFFFF)>>8;
        PIXEL* PSrcLineColor= (PIXEL*)((unsigned char*)(pSrc)+Src_Pitch*(srcy_16>>16));

        unsigned long srcx_16=0;
        for (int x=0;x<dst_width;++x)
        {
            PIXEL* PColor0=&PSrcLineColor[srcx_16>>16];
            pDst[x]=BilInearC4A(PColor0,(PIXEL*)((unsigned char*)PColor0+Src_Pitch),(srcx_16 & 0xFFFF)>>8,v_8);
            srcx_16+=xrIntFloat_16;
        }

        srcy_16+=yrIntFloat_16;
        ((unsigned char*&)pDst)+=Dst.nPitch;
    }
}





//
void WarpPerspective_8u_C4A(IMAGE& Src, IMAGE& Dst, int nWidth, int nLHeight, int nRHeight)
{

    unsigned int SrcW = Src.nWidth;
    unsigned int SrcH = Src.nHeight>>1;
    unsigned int DstW = nWidth;
    unsigned int DstHL = nLHeight>>1;
    unsigned int DstHR = nRHeight>>1;
    unsigned int DstHX16 = DstHL<<16;

    unsigned int Src_X16 = 0;
    unsigned int Src_Y16 = 0;
    unsigned int SrcXD16 = ((SrcW-1)<<16)/DstW+1;
    unsigned int SrcYD16 = ((SrcH-1)<<16)/DstHL+1;

    unsigned int dst_Pitch = Dst.nPitch;
    unsigned int Src_Pitch = Src.nPitch;

    PIXEL* pSrc = (PIXEL*)(Src.pData + Src_Pitch * SrcH);
    unsigned int y;

    if (DstHL >= DstHR) {
        PIXEL* pDst = (PIXEL*)(Dst.pData + dst_Pitch * DstHL);
        unsigned int DstHD16 = (DstHL<<16) - (((DstHR + DstHL * (DstW - 1)) <<16) / DstW);
        for (unsigned int x=0; x<DstW; x++) {

            unsigned int DstHX = DstHX16>>16;
            PIXEL* PSrcColumn=(pSrc+(Src_X16>>16));
            unsigned long u_8=(Src_X16 & 0xFFFF)>>8;

             PIXEL* dst = pDst+x;
             PIXEL* dstup = dst;

            Src_Y16 = 0;
            for (y=0; y<DstHX; y++) {
                PIXEL* PColor0 = (PIXEL*)((unsigned char*)PSrcColumn + Src_Pitch*(Src_Y16>>16));
                PIXEL* PColor1 = (PIXEL*)((unsigned char*)PSrcColumn - Src_Pitch*(Src_Y16>>16));
                *dst=BilInearC4A(PColor0,(PIXEL*)((unsigned char*)PColor0+Src_Pitch),u_8,(Src_Y16 & 0xFFFF)>>8);
                *dstup=BilInearC4A(PColor1,(PIXEL*)((unsigned char*)PColor1-Src_Pitch),u_8,((Src_Y16 & 0xFFFF))>>8);

                Src_Y16 += SrcYD16;
                ((unsigned char*&)dst)+=dst_Pitch;
                ((unsigned char*&)dstup)-=dst_Pitch;
            }
            for (y=0; y<DstHL - DstHX; y++) {
                *(int*)dst= 0;
                *(int*)dstup= 0;
                ((unsigned char*&)dst)+=dst_Pitch;
                ((unsigned char*&)dstup)-=dst_Pitch;
            }
            SrcYD16 = ((SrcH * DstW)<<16) / (DstHR * x + DstHL * (DstW - x));
            DstHX16 -= DstHD16;
            Src_X16 += SrcXD16;

        }
    }
    else {
        PIXEL* pDst = (PIXEL*)(Dst.pData + dst_Pitch * DstHR);
        unsigned int DstHD16 = (DstHR<<16) - (((DstHL + DstHR * (DstW - 1)) <<16)/ DstW);
        for (unsigned int x=0; x<DstW; x++) {

            unsigned int DstHX = DstHX16>>16;
            PIXEL* PSrcColumn=(pSrc+(Src_X16>>16));
            unsigned long u_8=(Src_X16 & 0xFFFF)>>8;

             PIXEL* dst = pDst+x;
             PIXEL* dstup = dst;

            Src_Y16 = 0;
            for (y=0; y<DstHX; y++) {
                PIXEL* PColor0 = (PIXEL*)((unsigned char*)PSrcColumn + Src_Pitch*(Src_Y16>>16));
                PIXEL* PColor1 = (PIXEL*)((unsigned char*)PSrcColumn - Src_Pitch*(Src_Y16>>16));
                *dst=BilInearC4A(PColor0,(PIXEL*)((unsigned char*)PColor0+Src_Pitch),u_8,(Src_Y16 & 0xFFFF)>>8);
                *dstup=BilInearC4A(PColor1,(PIXEL*)((unsigned char*)PColor1-Src_Pitch),u_8,((Src_Y16 & 0xFFFF))>>8);

                Src_Y16 += SrcYD16;
                ((unsigned char*&)dst)+=dst_Pitch;
                ((unsigned char*&)dstup)-=dst_Pitch;
            }
            for (y=0; y<DstHR - DstHX; y++) {
                *(int*)dst= 0;
                *(int*)dstup= 0;
                ((unsigned char*&)dst)+=dst_Pitch;
                ((unsigned char*&)dstup)-=dst_Pitch;
            }
            SrcYD16 = ((SrcH * DstW)<<16) / (DstHR * x + DstHL * (DstW - x));
            DstHX16 += DstHD16;
            Src_X16 += SrcXD16;
        }
    }
}

inline PIXEL BilInearNC4A(PIXEL* PColor0, PIXEL* PColor1,unsigned long u_8,unsigned long v_8)
{
    unsigned long pm3_16=u_8*v_8;
    unsigned long pm2_16=(u_8<<8)-pm3_16;
    unsigned long pm1_16=(v_8<<8)-pm3_16;
    unsigned long pm0_16=(65535)-pm1_16-pm2_16-pm3_16;

    PIXEL result;

    result.A =(unsigned char)((pm0_16*PColor0[1].A+pm2_16*PColor0[0].A+pm1_16*PColor1[1].A+pm3_16*PColor1[0].A)>>16);
    result.R =(unsigned char)((pm0_16*PColor0[1].R+pm2_16*PColor0[0].R+pm1_16*PColor1[1].R+pm3_16*PColor1[0].R)>>16);
    result.G =(unsigned char)((pm0_16*PColor0[1].G+pm2_16*PColor0[0].G+pm1_16*PColor1[1].G+pm3_16*PColor1[0].G)>>16);
    result.B =(unsigned char)((pm0_16*PColor0[1].B+pm2_16*PColor0[0].B+pm1_16*PColor1[1].B+pm3_16*PColor1[0].B)>>16);

    return result;
}

void WarpPerspectiveH_8u_C4A(IMAGE& Src, IMAGE& Dst, int nWidthT, int nWidthD, int nHeight)
{


    unsigned int SrcW = Src.nWidth>>1;
    unsigned int SrcH = Src.nHeight;
    unsigned int DstH = nHeight;
    unsigned int DstWT = nWidthT>>1;
    unsigned int DstWD = nWidthD>>1;
    unsigned int DstWX16 = DstWT<<16;

    if ((DstH<=1) || (DstWT<=1)) return;

    unsigned int Src_X16 = 0;
    unsigned int Src_Y16 = 0;
    unsigned int SrcYD16 = ((((SrcH-1)<<16))/(DstH))+1;
    unsigned int SrcXD16 = ((((SrcW-1)<<16))/(DstWT))+1;

    unsigned int dst_Pitch = Dst.nPitch;
    unsigned int Src_Pitch = Src.nPitch;

    PIXEL* pSrc = (PIXEL*)Src.pData + SrcW;

    unsigned int y;

    if (DstWT >= DstWD) {
        PIXEL* pDst = (PIXEL*)Dst.pData + DstWT;
        unsigned int DstWD16 = (DstWT<<16) - (((DstWD + DstWT * (DstH - 1)) <<16)/ DstH);
        for (unsigned int x=0; x<DstH; x++) {

            unsigned int DstWX = DstWX16>>16;
            PIXEL* PSrcColumn=(PIXEL*)((unsigned char*)pSrc+Src_Pitch*(Src_Y16>>16));
            unsigned long v_8=(Src_Y16 & 0xFFFF)>>8;

             PIXEL* dst = (PIXEL*)((unsigned char*)pDst+x*dst_Pitch);
             PIXEL* dstl = dst;

            Src_X16 = 0;
            for (y=0; y<DstWX; y++) {
                PIXEL* PColor0 = PSrcColumn + (Src_X16>>16);
                PIXEL* PColor1 = PSrcColumn - (Src_X16>>16);
                *dst=BilInearC4A(PColor0,(PIXEL*)((unsigned char*)PColor0+Src_Pitch), (Src_X16 & 0xFFFF)>>8, v_8);
                *dstl=BilInearNC4A(PColor1,(PIXEL*)((unsigned char*)PColor1+Src_Pitch), (Src_X16 & 0xFFFF)>>8, v_8);

                Src_X16 += SrcXD16;
                dst++;
                dstl--;
            }
            for (y=0; y<DstWT - DstWX; y++) {
                *(int*)dst= 0;
                *(int*)dstl= 0;
                dst++;
                dstl--;
            }
            SrcXD16 = ((SrcW * DstH)<<16) / (DstWD * x + DstWT * (DstH - x));
            DstWX16 -= DstWD16;
            Src_Y16 += SrcYD16;

        }
    }
    else {
        PIXEL* pDst = (PIXEL*)Dst.pData + DstWD;
        unsigned int DstWD16 = (DstWD<<16) - (((DstWT + DstWD * (DstH - 1)) <<16)/ DstH);
        for (unsigned int x=0; x<DstH; x++) {

            unsigned int DstWX = DstWX16>>16;
            PIXEL* PSrcColumn=(PIXEL*)((unsigned char*)pSrc+Src_Pitch*(Src_Y16>>16));
            unsigned long v_8=(Src_Y16 & 0xFFFF)>>8;

             PIXEL* dst = (PIXEL*)((unsigned char*)pDst+x*dst_Pitch);
             PIXEL* dstl = dst;

            Src_X16 = 0;
            for (y=0; y<DstWX; y++) {
                PIXEL* PColor0 = PSrcColumn + (Src_X16>>16);
                PIXEL* PColor1 = PSrcColumn - (Src_X16>>16);
                *dst=BilInearC4A(PColor0,(PIXEL*)((unsigned char*)PColor0+Src_Pitch), (Src_X16 & 0xFFFF)>>8, v_8);
                *dstl=BilInearNC4A(PColor1,(PIXEL*)((unsigned char*)PColor1+Src_Pitch), (Src_X16 & 0xFFFF)>>8, v_8);

                Src_X16 += SrcXD16;
                dst++;
                dstl--;
            }
            for (y=0; y<DstWD - DstWX; y++) {
                *(int*)dst= 0;
                *(int*)dstl= 0;
                dst++;
                dstl--;
            }
            SrcXD16 = ((SrcW * DstH)<<16) / (DstWD * x + DstWT * (DstH - x));
            DstWX16 += DstWD16;
            Src_Y16 += SrcYD16;
        }
    }
}


inline PIXEL Reflect(PIXEL pixel, unsigned char level)
{
    PIXEL result;
    result.R = (pixel.R*level)>>8;
    result.G = (pixel.G*level)>>8;
    result.B = (pixel.B*level)>>8;
    result.A = pixel.A;
    return result;
}

void AlbumTransform_8u_C4A(IMAGE& Src, IMAGE& Dst, int nWidthT, int nWidthD, int nHeight)
{
    unsigned int SrcW = Src.nWidth>>1;
    unsigned int SrcH = Src.nHeight;
    unsigned int DstH = nHeight;
    unsigned int DstWT = nWidthT>>1;
    unsigned int DstWD = nWidthD>>1;
    unsigned int DstWX16 = DstWT<<16;

    if ((DstH<=1) || (DstWT<=1)) return;

    unsigned int Src_X16 = 0;
    unsigned int Src_Y16 = 0;
    unsigned int SrcYD16 = ((((SrcH-1)<<16))/(DstH-1));
    unsigned int SrcXD16 = ((((SrcW-1)<<16))/(DstWT-1));

    unsigned int dst_Pitch = Dst.nPitch;
    unsigned int Src_Pitch = Src.nPitch;

    PIXEL* pSrc = (PIXEL*)Src.pData + SrcW;

    unsigned int y;

    if (DstWT >= DstWD) {
        PIXEL* pDst = (PIXEL*)Dst.pData + 3 * DstWT;
        int dec = 100/DstWT+1;
        unsigned int DstWD16 = (DstWT<<16) - (((DstWD + DstWT * (DstH - 1)) <<16)/ DstH);
        for (unsigned int x=0; x<DstH; x++) {

            unsigned int DstWX = DstWX16>>16;
            PIXEL* PSrcColumn=(PIXEL*)((unsigned char*)pSrc+Src_Pitch*(Src_Y16>>16));
            unsigned long v_8=(Src_Y16 & 0xFFFF)>>8;

            PIXEL* dst = (PIXEL*)((unsigned char*)pDst+x*dst_Pitch);
            PIXEL* dstl = dst;

            Src_X16 = 0;
            for (y=0; y<DstWX; y++) {
                PIXEL* PColor0 = PSrcColumn + (Src_X16>>16);
                PIXEL* PColor1 = PSrcColumn - (Src_X16>>16);
                *dst=BilInearC4A(PColor0,(PIXEL*)((unsigned char*)PColor0+Src_Pitch), (Src_X16 & 0xFFFF)>>8, v_8);
                *dstl=BilInearNC4A(PColor1,(PIXEL*)((unsigned char*)PColor1+Src_Pitch), (Src_X16 & 0xFFFF)>>8, v_8);

                Src_X16 += SrcXD16;
                dst++;
                dstl--;
            }
            for (y=0; y<DstWT - DstWX; y++) {
                *(int*)dst= 0;
                dst++;
            }
            dst=dstl+1;
            int level = 200;
            for (y=0; y<2*DstWX; y++) {
                if (level>0) level-=dec;
                if (level<0) level=0;
                *dstl=Reflect(*dst, level);
                dst++;
                dstl--;
            }
            for (y=0; y<3*(DstWT - DstWX); y++) {
                *(int*)dstl= 0;
                dstl--;
            }
            SrcXD16 = ((SrcW * DstH)<<16) / (DstWD * x + DstWT * (DstH - x));
            DstWX16 -= DstWD16;
            Src_Y16 += SrcYD16;

        }
    }
    else {
        PIXEL* pDst = (PIXEL*)Dst.pData + 3 * DstWD;
        int dec = 100/DstWD+1;
        unsigned int DstWD16 = (DstWD<<16) - (((DstWT + DstWD * (DstH - 1)) <<16)/ DstH);
        for (unsigned int x=0; x<DstH; x++) {

            unsigned int DstWX = DstWX16>>16;
            PIXEL* PSrcColumn=(PIXEL*)((unsigned char*)pSrc+Src_Pitch*(Src_Y16>>16));
            unsigned long v_8=(Src_Y16 & 0xFFFF)>>8;

             PIXEL* dst = (PIXEL*)((unsigned char*)pDst+x*dst_Pitch);
             PIXEL* dstl = dst;

            Src_X16 = 0;
            for (y=0; y<DstWX; y++) {
                PIXEL* PColor0 = PSrcColumn + (Src_X16>>16);
                PIXEL* PColor1 = PSrcColumn - (Src_X16>>16);
                *dst=BilInearC4A(PColor0,(PIXEL*)((unsigned char*)PColor0+Src_Pitch), (Src_X16 & 0xFFFF)>>8, v_8);
                *dstl=BilInearNC4A(PColor1,(PIXEL*)((unsigned char*)PColor1+Src_Pitch), (Src_X16 & 0xFFFF)>>8, v_8);

                Src_X16 += SrcXD16;
                dst++;
                dstl--;
            }
            for (y=0; y<DstWD - DstWX; y++) {
                *(int*)dst= 0;
                dst++;
            }
            dst=dstl+1;
            int level = 200;
            for (y=0; y<2*DstWX; y++) {
                if (level>0) level-=dec;
                if (level<0) level=0;
                *dstl=Reflect(*dst, level);
                dst++;
                dstl--;
            }
            for (y=0; y<3*(DstWD - DstWX); y++) {
                *(int*)dstl= 0;
                dstl--;
            }
            SrcXD16 = ((SrcW * DstH)<<16) / (DstWD * x + DstWT * (DstH - x));
            DstWX16 += DstWD16;
            Src_Y16 += SrcYD16;
        }
    }
}

void ShearBilinear_8u_C4A(IMAGE& Src, IMAGE& Dst, int offset)
{
    if ((abs(offset)+1)>Dst.nWidth)
        return;
    PIXEL* pSrc = (PIXEL*)Src.pData;

    unsigned int SrcW = Src.nWidth;
    unsigned int SrcH = Src.nHeight;
    unsigned int DstW = Dst.nWidth - abs(offset);
    unsigned int DstH =  Dst.nHeight;

    unsigned int SrcXD16 = ((SrcW-1)<<16)/(DstW)+1;
    unsigned int SrcYD16 = ((SrcH-1)<<16)/(DstH)+1;
    unsigned int DstSX16 = (abs(offset)<<16)/DstH;

    int dstwidth = DstW;
    int Src_Pitch = Src.nPitch;

    unsigned long srcy_16=0;
    int x;

    if (offset>=0) {
        PIXEL* pDst = (PIXEL*)Dst.pData;
        unsigned int Dst_SX16 = 0;
        for (int y=0;y<Dst.nHeight;++y) {
            unsigned long v_8=(srcy_16 & 0xFFFF)>>8;
            PIXEL* PSrcLineColor= (PIXEL*)((unsigned char*)(pSrc)+Src_Pitch*(srcy_16>>16));

            unsigned long srcx_16 = (0xFFFF - ((Dst_SX16) & 0xFFFF))*SrcW/DstW;

            for (x=0; x<int(Dst_SX16>>16); x++) {
                *(int*)pDst= 0;
                pDst++;
            }
            for (x=0; x<dstwidth; x++)
            {
                PIXEL* PColor0=&PSrcLineColor[srcx_16>>16];
                *pDst=BilInearC4A(PColor0,(PIXEL*)((unsigned char*)PColor0+Src_Pitch),(srcx_16 & 0xFFFF)>>8,v_8);
                srcx_16+=SrcXD16;
                pDst++;
            }
            for (x=0; x<offset - int(Dst_SX16>>16); x++) {
                *(int*)pDst= 0;
                pDst++;
            }
            Dst_SX16+=DstSX16;
            srcy_16+=SrcYD16;
            pDst = (PIXEL*)(Dst.pData + y * Dst.nPitch);
        }
    }
    else {
        PIXEL* pDst = (PIXEL*)Dst.pData - offset;
        unsigned int Dst_SX16 = abs(offset)<<16;
        for (int y=0;y<Dst.nHeight;++y) {
            unsigned long v_8=(srcy_16 & 0xFFFF)>>8;
            PIXEL* PSrcLineColor= (PIXEL*)((unsigned char*)(pSrc)+Src_Pitch*(srcy_16>>16));

            unsigned long srcx_16 = (0xFFFF - ((Dst_SX16) & 0xFFFF))*SrcW/DstW;
            for (x=0; x<int(Dst_SX16>>16); x++) {
                *(int*)pDst= 0;
                pDst++;
            }
            for (x=0; x<dstwidth; x++)
            {
                PIXEL* PColor0=&PSrcLineColor[srcx_16>>16];
                *pDst=BilInearC4A(PColor0,(PIXEL*)((unsigned char*)PColor0+Src_Pitch),(srcx_16 & 0xFFFF)>>8,v_8);
                srcx_16+=SrcXD16;
                pDst++;
            }
            for (x=0; x<-offset - int(Dst_SX16>>16); x++) {
                *(int*)pDst= 0;
                pDst++;
            }
            Dst_SX16-=DstSX16;
            srcy_16+=SrcYD16;
            pDst = (PIXEL*)(Dst.pData + y * Dst.nPitch);
        }
    }
}

void CurveBilinear_8u_C4A(IMAGE& Src, IMAGE& Dst, int* aSampleX16, int width)
{
    PIXEL* pSrc = (PIXEL*)Src.pData;

    int SrcW = Src.nWidth;
    int SrcH = Src.nHeight;
    int DstW = Dst.nWidth;
    int DstH = Dst.nHeight;

    unsigned int SrcXD16 = ((SrcW-1)<<16)/(width)+1;
    unsigned int SrcYD16 = ((SrcH-1)<<16)/(DstH)+1;
    unsigned int Dst_SX16 = aSampleX16[0];

    int dstwidth = width;
    int Src_Pitch = Src.nPitch;

    unsigned long srcy_16=0;
    int x;

    PIXEL* pDst = (PIXEL*)Dst.pData + (Dst_SX16>>16);

    for (int y=0;y<Dst.nHeight;y++) {

        Dst_SX16 = aSampleX16[y];

        unsigned long v_8=(srcy_16 & 0xFFFF)>>8;
        PIXEL* PSrcLineColor= (PIXEL*)((unsigned char*)(pSrc)+Src_Pitch*(srcy_16>>16));
        unsigned long srcx_16 = (0xFFFF - ((Dst_SX16) & 0xFFFF))*SrcW/dstwidth;

        for (x=0; x<int(Dst_SX16>>16); x++) {
            *(int*)pDst= 0;
            pDst++;
        }
        for (x=0; x<dstwidth; x++)
        {
            PIXEL* PColor0=&PSrcLineColor[srcx_16>>16];
            *pDst=BilInearC4A(PColor0,(PIXEL*)((unsigned char*)PColor0+Src_Pitch),(srcx_16 & 0xFFFF)>>8,v_8);
            srcx_16+=SrcXD16;
            pDst++;
        }
        for (x=0; x<DstW - dstwidth - int(Dst_SX16>>16); x++) {
            *(int*)pDst= 0;
            pDst++;
        }
        srcy_16+=SrcYD16;
        pDst = (PIXEL*)(Dst.pData + y * Dst.nPitch);
    }
}

void AdditiveCurveBilinearV_8u_C4A(IMAGE& Src, IMAGE& Dst, int* aSampleX16, int offset, int width)
{
    PIXEL* pSrc = (PIXEL*)Src.pData;

    int SrcW = Src.nWidth;
    int SrcH = Src.nHeight;
//    int DstW = Dst.nWidth;
    int DstH = Dst.nHeight;

    unsigned int SrcXD16 = ((SrcW-1)<<16)/(width)+1;
    unsigned int SrcYD16 = ((SrcH-1)<<16)/(DstH)+1;
    unsigned int Dst_SX16 = aSampleX16[0];

    int dstwidth = width;
    int Src_Pitch = Src.nPitch;

    unsigned long srcy_16=0;

    PIXEL* pDst = (PIXEL*)Dst.pData + (offset<<2);

    for (int y=0;y<Dst.nHeight;y++) {

        Dst_SX16 = aSampleX16[y];

        unsigned long v_8=(srcy_16 & 0xFFFF)>>8;
        PIXEL* PSrcLineColor= (PIXEL*)((unsigned char*)(pSrc)+Src_Pitch*(srcy_16>>16));
        unsigned long srcx_16 = (0xFFFF - ((Dst_SX16) & 0xFFFF))*SrcW/dstwidth;

        pDst+= (Dst_SX16>>16);

        for (int x=0; x<dstwidth; x++) {
            PIXEL* PColor0=&PSrcLineColor[srcx_16>>16];
            *pDst=Add(BilInearC4A(PColor0,(PIXEL*)((unsigned char*)PColor0+Src_Pitch),(srcx_16 & 0xFFFF)>>8,v_8),*pDst);
            srcx_16+=SrcXD16;
            pDst++;
        }

        srcy_16+=SrcYD16;
        pDst = (PIXEL*)(Dst.pData + y * Dst.nPitch);
    }
}

void AdditiveCurveBilinearH_8u_C4A(IMAGE& Src, IMAGE& Dst, int* aSampleX16, int offset, int height)
{
    PIXEL* pSrc = (PIXEL*)Src.pData;

    int SrcW = Src.nWidth;
    int SrcH = Src.nHeight;
    int DstW = Dst.nWidth;
//    int DstH = Dst.nHeight;

    unsigned int SrcXD16 = ((SrcW-1)<<16)/(DstW)+1;
    unsigned int SrcYD16 = ((SrcH-1)<<16)/(height)+1;
    unsigned int Dst_SY16 = aSampleX16[0];

    int dstheight = height;
    int Src_Pitch = Src.nPitch;

    unsigned long srcx_16=0;

    PIXEL* pDst = (PIXEL*)Dst.pData + (offset*Dst.nPitch);

    for (int y=0;y<Dst.nWidth;y++) {

        Dst_SY16 = aSampleX16[y];

        unsigned long u_8=(srcx_16 & 0xFFFF)>>8;
        PIXEL* PSrcLineColor= (PIXEL*)((unsigned char*)(pSrc)+((srcx_16>>16)<<2));
        unsigned long srcy_16 = (0xFFFF - ((Dst_SY16) & 0xFFFF))*SrcH/dstheight;

        ((char*&)pDst)+= (Dst_SY16>>16)*Dst.nPitch;

        for (int x=0; x<dstheight; x++) {
            PIXEL* PColor0 = PSrcLineColor;
            ((char*&)PColor0)+=(srcy_16>>16)*Src_Pitch;
            *pDst=Add(BilInearC4A(PColor0,(PIXEL*)((unsigned char*)PColor0+Src_Pitch),u_8,(srcy_16 & 0xFFFF)>>8),*pDst);
            srcy_16+=SrcYD16;
            ((char*&)pDst)+= Dst.nPitch;
        }

        srcx_16+=SrcXD16;
        pDst = (PIXEL*)(Dst.pData + (y<<2));
    }
}

void SinWave_32u(_SINWAVE & sinwave)
{
//    int* pDst;
//    int len;
//    int magQ15;
//    int freqQ15;
//    int phaseQ15;
//    int Scale;

    for (int i=0; i<sinwave.len; i++) {
        sinwave.pDst[i] = 0;
    }
}

void RECT888To565(IMAGE * image, SURFACE * surface)
{
    int x, y, width, height;
    width = image->nWidth;
    height = image->nHeight;
    PIXEL* Src = (PIXEL*)image->pData;
    short * Dst = surface->pData;
    short temp;
    for (y=0;y<height;y++) {
        for (x=0;x<width;x++) {
            temp = Src[x].B>>3;
            temp |= (Src[x].G>>2)<<5;
            temp |= (Src[x].R>>3)<<11;
            Dst[x] = temp;
        }
        ((char*&)Src)+=image->nPitch;
        ((char*&)Dst)+=surface->nPitch;
    }
}

void RECT888To565RCW(IMAGE * image, SURFACE * surface)
{
    int x, y, width, height;
    width = image->nWidth;
    height = image->nHeight;
    PIXEL* Src = (PIXEL*)image->pData;
    ((char*&)Src)+=image->nPitch*(image->nHeight-1);
    short * Dst = surface->pData;
    short * DstLine = Dst;
    short temp;
    for (y=0;y<height;y++) {
        for (x=0;x<width;x++) {
            temp = Src[x].B>>3;
            temp |= (Src[x].G>>2)<<5;
            temp |= (Src[x].R>>3)<<11;
            *Dst = temp;
            ((char*&)Dst)+=surface->nPitch;
        }
        ((char*&)Src)-=image->nPitch;
        DstLine+=1;
        Dst = DstLine;
    }
}

void RECT888To565RCCW(IMAGE * image, SURFACE * surface)
{
    int x, y, width, height;
    width = image->nWidth;
    height = image->nHeight;
    PIXEL* Src = (PIXEL*)image->pData;
    short * Dst = surface->pData;
    short * DstLine = Dst;
    short temp;
    for (y=0;y<height;y++) {
        for (x=0;x<width;x++) {
            temp = Src[x].B>>3;
            temp |= (Src[x].G>>2)<<5;
            temp |= (Src[x].R>>3)<<11;
            *Dst = temp;
            ((char*&)Dst)-=surface->nPitch;
        }
        ((char*&)Src)+=image->nPitch;
        DstLine+=1;
        Dst = DstLine;
    }
}

void RECT888To565FLIP(IMAGE * image, SURFACE * surface)
{
    int x, y, width, height;
    width = image->nWidth;
    height = image->nHeight;
    PIXEL* Src = (PIXEL*)image->pData;
    short * Dst = surface->pData;
    short * DstLine = Dst;
    short temp;
    for (y=0;y<height;y++) {
        for (x=0;x<width;x++) {
            temp = Src[x].B>>3;
            temp |= (Src[x].G>>2)<<5;
            temp |= (Src[x].R>>3)<<11;
            *--Dst = temp;
        }
        ((char*&)Src)+=image->nPitch;
        ((char*&)DstLine)-=surface->nPitch;
        Dst = DstLine;
    }
}
//
//void RGB888To565(IMAGE &image, SURFACE &surface, INVALIDREGION &rect, int orientation)
//{
//    IMAGE Src = image;
//    SURFACE Dst = surface;
////    DebugBreak();
//    switch (orientation) {
//        case 0:
//            Src.pData += (rect.tx+rect.ty*image.nWidth)<<2;
//            Src.nWidth = rect.bx - rect.tx;
//            Src.nHeight = rect.by - rect.ty;
//            Dst.pData += (rect.tx+rect.ty*surface.nWidth);
//            Dst.nPitch = surface.nPitch;
//            RECT888To565(&Src,&Dst);
//            break;
//        case 1:
//            Src.pData += (rect.tx+rect.ty*image.nWidth)<<2;
//            Src.nWidth = rect.bx - rect.tx;
//            Src.nHeight = rect.by - rect.ty;
//            Dst.pData += (surface.nWidth-rect.by)+rect.tx*surface.nWidth;
//            Dst.nPitch = surface.nPitch;
//            RECT888To565RCW(&Src,&Dst);
//            break;
//        case 2:
//            Src.pData += (rect.tx+rect.ty*image.nWidth)<<2;
//            Src.nWidth = rect.bx - rect.tx;
//            Src.nHeight = rect.by - rect.ty;
//            Dst.pData += (surface.nWidth-rect.tx)+(surface.nHeight-rect.ty-1)*surface.nWidth;
//            Dst.nPitch = surface.nPitch;
//            RECT888To565FLIP(&Src, &Dst);
//            break;
//        case 3:
//            Src.pData += (rect.tx+rect.ty*image.nWidth)<<2;
//            Src.nWidth = rect.bx - rect.tx;
//            Src.nHeight = rect.by - rect.ty;
//            Dst.pData += rect.ty + (surface.nHeight-rect.tx-1)*surface.nWidth;
//            Dst.nPitch = surface.nPitch;
//            RECT888To565RCCW(&Src,&Dst);
//            break;
//    }
//}

void RECT888To666(IMAGE * image, IMAGE * surface)
{
    int x, y, width, height;
    width = image->nWidth;
    height = image->nHeight;
    PIXEL* Src = (PIXEL*)image->pData;
    int * Dst = (int*)surface->pData;
    int temp;
    for (y=0;y<height;y++) {
        for (x=0;x<width;x++) {
            temp = Src[x].B>>2;
            temp |= (Src[x].G>>2)<<6;
            temp |= (Src[x].R>>2)<<12;
            Dst[x] = temp;
        }
        ((char*&)Src)+=image->nPitch;
        ((char*&)Dst)+=surface->nPitch;
    }
}

void RECT888To666RCW(IMAGE * image, IMAGE * surface)
{
    int x, y, width, height;
    width = image->nWidth;
    height = image->nHeight;
    PIXEL* Src = (PIXEL*)image->pData;
    ((char*&)Src)+=image->nPitch*(image->nHeight-1);
    int * Dst = (int*)surface->pData;
    int * DstLine = Dst;
    int temp;
    for (y=0;y<height;y++) {
        for (x=0;x<width;x++) {
            temp = Src[x].B>>2;
            temp |= (Src[x].G>>2)<<6;
            temp |= (Src[x].R>>2)<<12;
            *Dst = temp;
            ((char*&)Dst)+=surface->nPitch;
        }
        ((char*&)Src)-=image->nPitch;
        DstLine+=1;
        Dst = DstLine;
    }
}

void RECT888To666RCCW(IMAGE * image, IMAGE * surface)
{
    int x, y, width, height;
    width = image->nWidth;
    height = image->nHeight;
    PIXEL* Src = (PIXEL*)image->pData;
    int * Dst = (int*)surface->pData;
    int * DstLine = Dst;
    int temp;
    for (y=0;y<height;y++) {
        for (x=0;x<width;x++) {
            temp = Src[x].B>>2;
            temp |= (Src[x].G>>2)<<6;
            temp |= (Src[x].R>>2)<<12;
            *Dst = temp;
            ((char*&)Dst)-=surface->nPitch;
        }
        ((char*&)Src)+=image->nPitch;
        DstLine+=1;
        Dst = DstLine;
    }
}

void RECT888To666FLIP(IMAGE * image, IMAGE * surface)
{
    int x, y, width, height;
    width = image->nWidth;
    height = image->nHeight;
    PIXEL* Src = (PIXEL*)image->pData;
    int * Dst = (int*)surface->pData;
    int * DstLine = Dst;
    int temp;
    for (y=0;y<height;y++) {
        for (x=0;x<width;x++) {
            temp = Src[x].B>>2;
            temp |= (Src[x].G>>2)<<6;
            temp |= (Src[x].R>>2)<<12;
            *--Dst = temp;
        }
        ((char*&)Src)+=image->nPitch;
        ((char*&)DstLine)-=surface->nPitch;
        Dst = DstLine;
    }
}
//
//void RGB888To666(IMAGE &image, IMAGE &surface, INVALIDREGION &rect, int orientation)
//{
//    IMAGE Src = image;
//    IMAGE Dst = surface;
//
//    switch (orientation) {
//        case 0:
//            Src.pData += (rect.tx+rect.ty*image.nWidth)<<2;
//            Src.nWidth = rect.bx - rect.tx;
//            Src.nHeight = rect.by - rect.ty;
//            Dst.pData += (rect.tx+rect.ty*surface.nWidth)<<2;
//            Dst.nPitch = surface.nPitch;
//            RECT888To666(&Src,&Dst);
//            break;
//        case 1:
//            Src.pData += (rect.tx+rect.ty*image.nWidth)<<2;
//            Src.nWidth = rect.bx - rect.tx;
//            Src.nHeight = rect.by - rect.ty;
//            Dst.pData += ((surface.nWidth-rect.by)+rect.tx*surface.nWidth)<<2;
//            Dst.nPitch = surface.nPitch;
//            RECT888To666RCW(&Src,&Dst);
//            break;
//        case 2:
//            Src.pData += (rect.tx+rect.ty*image.nWidth)<<2;
//            Src.nWidth = rect.bx - rect.tx;
//            Src.nHeight = rect.by - rect.ty;
//            Dst.pData += ((surface.nWidth-rect.tx)+(surface.nHeight-rect.ty-1)*surface.nWidth)<<2;
//            Dst.nPitch = surface.nPitch;
//            RECT888To666FLIP(&Src, &Dst);
//            break;
//        case 3:
//            Src.pData += (rect.tx+rect.ty*image.nWidth)<<2;
//            Src.nWidth = rect.bx - rect.tx;
//            Src.nHeight = rect.by - rect.ty;
//            Dst.pData += (rect.ty + (surface.nHeight-rect.tx-1)*surface.nWidth)<<2;
//            Dst.nPitch = surface.nPitch;
//            RECT888To666RCCW(&Src,&Dst);
//            break;
//    }
//}
//


void RECTBLIT(IMAGE * image, IMAGE * surface)
{
    int x, y, width, height;
    width = image->nWidth;
    height = image->nHeight;
    PIXEL* Src = (PIXEL*)image->pData;
    PIXEL* Dst = (PIXEL*)surface->pData;
    for (y=0;y<height;y++) {
        for (x=0;x<width;x++) {
            Dst[x] = Src[x];
        }
        ((char*&)Src)+=image->nPitch;
        ((char*&)Dst)+=surface->nPitch;
    }
}

void RECTBLITRCW(IMAGE * image, IMAGE * surface)
{
    int x, y, width, height;
    width = image->nWidth;
    height = image->nHeight;
    PIXEL* Src = (PIXEL*)image->pData;
    ((char*&)Src)+=image->nPitch*(image->nHeight-1);
    PIXEL * Dst = (PIXEL*)surface->pData;
    PIXEL * DstLine = Dst;
    for (y=0;y<height;y++) {
        for (x=0;x<width;x++) {
             *Dst =  Src[x];
            ((char*&)Dst)+=surface->nPitch;
        }
        ((char*&)Src)-=image->nPitch;
        DstLine+=1;
        Dst = DstLine;
    }
}

void RECTBLITRCCW(IMAGE * image, IMAGE * surface)
{
    int x, y, width, height;
    width = image->nWidth;
    height = image->nHeight;
    PIXEL* Src = (PIXEL*)image->pData;
    PIXEL * Dst = (PIXEL*)surface->pData;
    PIXEL * DstLine = Dst;
    for (y=0;y<height;y++) {
        for (x=0;x<width;x++) {
            *Dst = Src[x];
            ((char*&)Dst)-=surface->nPitch;
        }
        ((char*&)Src)+=image->nPitch;
        DstLine+=1;
        Dst = DstLine;
    }
}

void RECTBLITFLIP(IMAGE * image, IMAGE * surface)
{
    int x, y, width, height;
    width = image->nWidth;
    height = image->nHeight;
    PIXEL* Src = (PIXEL*)image->pData;
    PIXEL * Dst = (PIXEL*)surface->pData;
    PIXEL * DstLine = Dst;
    for (y=0;y<height;y++) {
        for (x=0;x<width;x++) {
            *--Dst = Src[x];
        }
        ((char*&)Src)+=image->nPitch;
        ((char*&)DstLine)-=surface->nPitch;
        Dst = DstLine;
    }
}

void RotateBlit(IMAGE &image, IMAGE &surface, INVALIDREGION &rect, int orientation)
{
    IMAGE Src = image;
    IMAGE Dst = surface;

    switch (orientation) {
        case 0:
            Src.pData += (rect.tx+rect.ty*image.nWidth)<<2;
            Src.nWidth = rect.bx - rect.tx;
            Src.nHeight = rect.by - rect.ty;
            Dst.pData += (rect.tx+rect.ty*surface.nWidth)<<2;
            Dst.nPitch = surface.nPitch;
            RECTBLIT(&Src,&Dst);
            break;
        case 1:
            Src.pData += (rect.tx+rect.ty*image.nWidth)<<2;
            Src.nWidth = rect.bx - rect.tx;
            Src.nHeight = rect.by - rect.ty;
            Dst.pData += ((surface.nWidth-rect.by)+rect.tx*surface.nWidth)<<2;
            Dst.nPitch = surface.nPitch;
            RECTBLITRCW(&Src,&Dst);
            break;
        case 2:
            Src.pData += (rect.tx+rect.ty*image.nWidth)<<2;
            Src.nWidth = rect.bx - rect.tx;
            Src.nHeight = rect.by - rect.ty;
            Dst.pData += ((surface.nWidth-rect.tx)+(surface.nHeight-rect.ty-1)*surface.nWidth)<<2;
            Dst.nPitch = surface.nPitch;
            RECTBLITFLIP(&Src, &Dst);
            break;
        case 3:
            Src.pData += (rect.tx+rect.ty*image.nWidth)<<2;
            Src.nWidth = rect.bx - rect.tx;
            Src.nHeight = rect.by - rect.ty;
            Dst.pData += (rect.ty + (surface.nHeight-rect.tx-1)*surface.nWidth)<<2;
            Dst.nPitch = surface.nPitch;
            RECTBLITRCCW(&Src,&Dst);
            break;
    }
}

void Dither_ErrorDiffuse_Line(PIXEL* pDst, PIXEL* pSrc,int width,_ErrorColor* PHLineErr, int Rbit, int Gbit, int Bbit)
{
    _ErrorColor HErr;

    int Bfactor = Power2m1(Bbit);
    int Gfactor = Power2m1(Gbit);
    int Rfactor = Power2m1(Rbit);

    HErr.dR=0; HErr.dG=0; HErr.dB=0;

    PHLineErr[-1].dB=0; PHLineErr[-1].dG=0; PHLineErr[-1].dR=0;

    for (long x=0;x<width;++x)
    {

        float cB=(pSrc[x].B+HErr.dB*2+PHLineErr[x].dB+PHLineErr[x-1].dB);
        float cG=(pSrc[x].G+HErr.dG*2+PHLineErr[x].dG+PHLineErr[x-1].dG);
        float cR=(pSrc[x].R+HErr.dR*2+PHLineErr[x].dR+PHLineErr[x-1].dR);

        int rB=getBestColor(cB, Bfactor);
        int rG=getBestColor(cG, Gfactor);
        int rR=getBestColor(cR, Rfactor);

        pDst[x].R = (unsigned char)rR;
        pDst[x].G = (unsigned char)rG;
        pDst[x].B = (unsigned char)rB;


        HErr.dB=float((cB-(rB*(255.0/Bfactor)))*(1.0/4));
        HErr.dG=float((cG-(rG*(255.0/Gfactor)))*(1.0/4));
        HErr.dR=float((cR-(rR*(255.0/Rfactor)))*(1.0/4));

        PHLineErr[x-1].dB+=HErr.dB;
        PHLineErr[x-1].dG+=HErr.dG;
        PHLineErr[x-1].dR+=HErr.dR;

        PHLineErr[x]=HErr;
    }
}

void Dither_ErrorDiffuse(IMAGE& dst,const IMAGE& src, int Rbit, int Gbit, int Bbit)
{
    PIXEL* pDst=(PIXEL*)dst.pData;
    PIXEL* pSrc=(PIXEL*)src.pData;
    int width=src.nWidth;

    _ErrorColor* _HLineErr=new _ErrorColor[width+2];

    for (long x=0;x<width+2;++x){
        _HLineErr[x].dR=0;
        _HLineErr[x].dG=0;
        _HLineErr[x].dB=0;
    }

    _ErrorColor* HLineErr=&_HLineErr[1];

    for (long y=0;y<src.nHeight;++y){
        Dither_ErrorDiffuse_Line(pDst,pSrc,width,HLineErr,Rbit,Gbit,Bbit);
        (unsigned char*&)pDst+=dst.nPitch;
        (unsigned char*&)pSrc+=src.nPitch;
    }

    delete[]_HLineErr;
}


void DitherImage(unsigned char * pData, int width, int height, int Rbit, int Gbit, int Bbit)
{
    IMAGE Src;
    IMAGE Dst;

    Src.pData = pData;
    Src.nWidth = width;
    Src.nHeight = height;
    Src.nPitch = width*4;

    Dst.pData = (unsigned char*)malloc(height * width * 4);
    Dst.nPitch = Src.nPitch;
    Dst.nWidth = Src.nWidth;
    Dst.nHeight = Src.nHeight;

    Dither_ErrorDiffuse(Dst,Src,Rbit,Gbit,Bbit);

    PIXEL* src = (PIXEL*)Src.pData;
    PIXEL* dst = (PIXEL*)Dst.pData;

    for (int i=0;i<width*height;i++) {
        (*src).R = (*dst).R<<(8-Rbit);
        (*src).G = (*dst).G<<(8-Gbit);
        (*src).B = (*dst).B<<(8-Bbit);
        dst++;
        src++;
    }

    if (Dst.pData) delete Dst.pData;
}
